xref: /petsc/src/mat/interface/matrix.c (revision af27ebaa0199971c43fd2e2e162251afd1bcda49)
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 PETSC_INTERN 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;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 . mat - the matrix
257 
258   Output Parameter:
259 . keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264   `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscAssertPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282   MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 . mat - the matrix
286 
287   Output Parameter:
288 . zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293   `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscAssertPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323   Not Collective
324 
325   Input Parameter:
326 . A - the matrix
327 
328   Output Parameter:
329 . a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331   Level: advanced
332 
333   Notes:
334   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscAssertPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361   Collective
362 
363   Input Parameter:
364 . mat - the matrix
365 
366   Output Parameter:
367 . trace - the sum of the diagonal entries
368 
369   Level: advanced
370 
371 .seealso: [](ch_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscAssertPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388   MatRealPart - Zeros out the imaginary part of the matrix
389 
390   Logically Collective
391 
392   Input Parameter:
393 . mat - the matrix
394 
395   Level: advanced
396 
397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414   Collective
415 
416   Input Parameter:
417 . mat - the matrix
418 
419   Output Parameters:
420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
421 - ghosts  - the global indices of the ghost points
422 
423   Level: advanced
424 
425   Note:
426   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
427 
428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448   Logically Collective
449 
450   Input Parameter:
451 . mat - the matrix
452 
453   Level: advanced
454 
455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
471 
472   Not Collective
473 
474   Input Parameter:
475 . mat - the matrix
476 
477   Output Parameters:
478 + missing - is any diagonal entry missing
479 - dd      - first diagonal entry that is missing (optional) on this process
480 
481   Level: advanced
482 
483   Note:
484   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
485 
486 .seealso: [](ch_matrices), `Mat`
487 @*/
488 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
489 {
490   PetscFunctionBegin;
491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
492   PetscValidType(mat, 1);
493   PetscAssertPointer(missing, 2);
494   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
495   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
496   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
497   PetscFunctionReturn(PETSC_SUCCESS);
498 }
499 
500 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
501 /*@C
502   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
503   for each row that you get to ensure that your application does
504   not bleed memory.
505 
506   Not Collective
507 
508   Input Parameters:
509 + mat - the matrix
510 - row - the row to get
511 
512   Output Parameters:
513 + ncols - if not `NULL`, the number of nonzeros in `row`
514 . cols  - if not `NULL`, the column numbers
515 - vals  - if not `NULL`, the numerical values
516 
517   Level: advanced
518 
519   Notes:
520   This routine is provided for people who need to have direct access
521   to the structure of a matrix.  We hope that we provide enough
522   high-level matrix routines that few users will need it.
523 
524   `MatGetRow()` always returns 0-based column indices, regardless of
525   whether the internal representation is 0-based (default) or 1-based.
526 
527   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
528   not wish to extract these quantities.
529 
530   The user can only examine the values extracted with `MatGetRow()`;
531   the values CANNOT be altered.  To change the matrix entries, one
532   must use `MatSetValues()`.
533 
534   You can only have one call to `MatGetRow()` outstanding for a particular
535   matrix at a time, per processor. `MatGetRow()` can only obtain rows
536   associated with the given processor, it cannot get rows from the
537   other processors; for that we suggest using `MatCreateSubMatrices()`, then
538   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
539   is in the global number of rows.
540 
541   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
542 
543   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
544 
545   Fortran Note:
546   The calling sequence is
547 .vb
548    MatGetRow(matrix,row,ncols,cols,values,ierr)
549          Mat     matrix (input)
550          integer row    (input)
551          integer ncols  (output)
552          integer cols(maxcols) (output)
553          double precision (or double complex) values(maxcols) output
554 .ve
555   where maxcols >= maximum nonzeros in any row of the matrix.
556 
557 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   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);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578   MatConjugate - replaces the matrix values with their complex conjugates
579 
580   Logically Collective
581 
582   Input Parameter:
583 . mat - the matrix
584 
585   Level: advanced
586 
587 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604   Not Collective
605 
606   Input Parameters:
607 + mat   - the matrix
608 . row   - the row to get
609 . ncols - the number of nonzeros
610 . cols  - the columns of the nonzeros
611 - vals  - if nonzero the column values
612 
613   Level: advanced
614 
615   Notes:
616   This routine should be called after you have finished examining the entries.
617 
618   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
619   us of the array after it has been restored. If you pass `NULL`, it will
620   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
621 
622   Fortran Notes:
623   The calling sequence is
624 .vb
625    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
626       Mat     matrix (input)
627       integer row    (input)
628       integer ncols  (output)
629       integer cols(maxcols) (output)
630       double precision (or double complex) values(maxcols) output
631 .ve
632   Where maxcols >= maximum nonzeros in any row of the matrix.
633 
634   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
635   before another call to `MatGetRow()` can be made.
636 
637 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
638 @*/
639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
640 {
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
643   if (ncols) PetscAssertPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657   Not Collective
658 
659   Input Parameter:
660 . mat - the matrix
661 
662   Level: advanced
663 
664   Note:
665   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.
666 
667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685   Not Collective
686 
687   Input Parameter:
688 . mat - the matrix
689 
690   Level: advanced
691 
692   Note:
693   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711   MatSetOptionsPrefix - Sets the prefix used for searching for all
712   `Mat` options in the database.
713 
714   Logically Collective
715 
716   Input Parameters:
717 + A      - the matrix
718 - prefix - the prefix to prepend to all option names
719 
720   Level: advanced
721 
722   Notes:
723   A hyphen (-) must NOT be given at the beginning of the prefix name.
724   The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726   This is NOT used for options for the factorization of the matrix. Normally the
727   prefix is automatically passed in from the PC calling the factorization. To set
728   it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742   for matrices created with `MatGetFactor()`
743 
744   Logically Collective
745 
746   Input Parameters:
747 + A      - the matrix
748 - prefix - the prefix to prepend to all option names for the factored matrix
749 
750   Level: developer
751 
752   Notes:
753   A hyphen (-) must NOT be given at the beginning of the prefix name.
754   The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscAssertPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778   for matrices created with `MatGetFactor()`
779 
780   Logically Collective
781 
782   Input Parameters:
783 + A      - the matrix
784 - prefix - the prefix to prepend to all option names for the factored matrix
785 
786   Level: developer
787 
788   Notes:
789   A hyphen (-) must NOT be given at the beginning of the prefix name.
790   The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822   matrix options in the database.
823 
824   Logically Collective
825 
826   Input Parameters:
827 + A      - the matrix
828 - prefix - the prefix to prepend to all option names
829 
830   Level: advanced
831 
832   Note:
833   A hyphen (-) must NOT be given at the beginning of the prefix name.
834   The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847   MatGetOptionsPrefix - Gets the prefix used for searching for all
848   matrix options in the database.
849 
850   Not Collective
851 
852   Input Parameter:
853 . A - the matrix
854 
855   Output Parameter:
856 . prefix - pointer to the prefix string used
857 
858   Level: advanced
859 
860   Fortran Note:
861   The user should pass in a string `prefix` of
862   sufficient length to hold the prefix.
863 
864 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
865 @*/
866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscAssertPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
877 
878   Collective
879 
880   Input Parameter:
881 . A - the matrix
882 
883   Level: beginner
884 
885   Notes:
886   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888   Users can reset the preallocation to access the original memory.
889 
890   Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
893 @*/
894 PetscErrorCode MatResetPreallocation(Mat A)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscValidType(A, 1);
899   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()");
900   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
901   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
902   PetscFunctionReturn(PETSC_SUCCESS);
903 }
904 
905 /*@
906   MatSetUp - Sets up the internal matrix data structures for later use.
907 
908   Collective
909 
910   Input Parameter:
911 . A - the matrix
912 
913   Level: intermediate
914 
915   Notes:
916   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
917   setting values in the matrix.
918 
919   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatSetUp(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   if (!((PetscObject)A)->type_name) {
928     PetscMPIInt size;
929 
930     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
931     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
932   }
933   if (!A->preallocated) PetscTryTypeMethod(A, setup);
934   PetscCall(PetscLayoutSetUp(A->rmap));
935   PetscCall(PetscLayoutSetUp(A->cmap));
936   A->preallocated = PETSC_TRUE;
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 #if defined(PETSC_HAVE_SAWS)
941   #include <petscviewersaws.h>
942 #endif
943 
944 /*
945    If threadsafety is on extraneous matrices may be printed
946 
947    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
948 */
949 #if !defined(PETSC_HAVE_THREADSAFETY)
950 static PetscInt insidematview = 0;
951 #endif
952 
953 /*@C
954   MatViewFromOptions - View properties of the matrix based on options set in the options database
955 
956   Collective
957 
958   Input Parameters:
959 + A    - the matrix
960 . obj  - optional additional object that provides the options prefix to use
961 - name - command line option
962 
963   Options Database Key:
964 . -mat_view [viewertype]:... - the viewer and its options
965 
966   Level: intermediate
967 
968   Note:
969 .vb
970     If no value is provided ascii:stdout is used
971        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
972                                                   for example ascii::ascii_info prints just the information about the object not all details
973                                                   unless :append is given filename opens in write mode, overwriting what was already there
974        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
975        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
976        socket[:port]                             defaults to the standard output port
977        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
978 .ve
979 
980 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
981 @*/
982 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
983 {
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
986 #if !defined(PETSC_HAVE_THREADSAFETY)
987   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
988 #endif
989   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
990   PetscFunctionReturn(PETSC_SUCCESS);
991 }
992 
993 /*@C
994   MatView - display information about a matrix in a variety ways
995 
996   Collective
997 
998   Input Parameters:
999 + mat    - the matrix
1000 - viewer - visualization context
1001 
1002   Options Database Keys:
1003 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1004 . -mat_view ::ascii_info_detail    - Prints more detailed info
1005 . -mat_view                        - Prints matrix in ASCII format
1006 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1007 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1008 . -display <name>                  - Sets display name (default is host)
1009 . -draw_pause <sec>                - Sets number of seconds to pause after display
1010 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1011 . -viewer_socket_machine <machine> - -
1012 . -viewer_socket_port <port>       - -
1013 . -mat_view binary                 - save matrix to file in binary format
1014 - -viewer_binary_filename <name>   - -
1015 
1016   Level: beginner
1017 
1018   Notes:
1019   The available visualization contexts include
1020 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1021 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1022 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1023 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1024 
1025   The user can open alternative visualization contexts with
1026 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1027 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1028   specified file; corresponding input uses `MatLoad()`
1029 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1030   an X window display
1031 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1032   Currently only the `MATSEQDENSE` and `MATAIJ`
1033   matrix types support the Socket viewer.
1034 
1035   The user can call `PetscViewerPushFormat()` to specify the output
1036   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1037   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1038 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1039 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1040 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1041 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1042   format common among all matrix types
1043 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1044   format (which is in many cases the same as the default)
1045 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1046   size and structure (not the matrix entries)
1047 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1048   the matrix structure
1049 
1050   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1051   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1052 
1053   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1054 
1055   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1056   viewer is used.
1057 
1058   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1059   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1060 
1061   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1062   and then use the following mouse functions.
1063 .vb
1064   left mouse: zoom in
1065   middle mouse: zoom out
1066   right mouse: continue with the simulation
1067 .ve
1068 
1069 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1070           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1071 @*/
1072 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1073 {
1074   PetscInt          rows, cols, rbs, cbs;
1075   PetscBool         isascii, isstring, issaws;
1076   PetscViewerFormat format;
1077   PetscMPIInt       size;
1078 
1079   PetscFunctionBegin;
1080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1081   PetscValidType(mat, 1);
1082   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1083   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1084   PetscCheckSameComm(mat, 1, viewer, 2);
1085 
1086   PetscCall(PetscViewerGetFormat(viewer, &format));
1087   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1088   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1089 
1090 #if !defined(PETSC_HAVE_THREADSAFETY)
1091   insidematview++;
1092 #endif
1093   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1096   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");
1097 
1098   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1099   if (isascii) {
1100     if (!mat->preallocated) {
1101       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1102 #if !defined(PETSC_HAVE_THREADSAFETY)
1103       insidematview--;
1104 #endif
1105       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1106       PetscFunctionReturn(PETSC_SUCCESS);
1107     }
1108     if (!mat->assembled) {
1109       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1110 #if !defined(PETSC_HAVE_THREADSAFETY)
1111       insidematview--;
1112 #endif
1113       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1114       PetscFunctionReturn(PETSC_SUCCESS);
1115     }
1116     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1117     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1118       MatNullSpace nullsp, transnullsp;
1119 
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatGetSize(mat, &rows, &cols));
1122       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1123       if (rbs != 1 || cbs != 1) {
1124         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1125         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1126       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1127       if (mat->factortype) {
1128         MatSolverType solver;
1129         PetscCall(MatFactorGetSolverType(mat, &solver));
1130         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1131       }
1132       if (mat->ops->getinfo) {
1133         MatInfo info;
1134         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1135         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1136         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1137       }
1138       PetscCall(MatGetNullSpace(mat, &nullsp));
1139       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1140       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1141       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1142       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1143       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1144       PetscCall(PetscViewerASCIIPushTab(viewer));
1145       PetscCall(MatProductView(mat, viewer));
1146       PetscCall(PetscViewerASCIIPopTab(viewer));
1147     }
1148   } else if (issaws) {
1149 #if defined(PETSC_HAVE_SAWS)
1150     PetscMPIInt rank;
1151 
1152     PetscCall(PetscObjectName((PetscObject)mat));
1153     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1154     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1155 #endif
1156   } else if (isstring) {
1157     const char *type;
1158     PetscCall(MatGetType(mat, &type));
1159     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1160     PetscTryTypeMethod(mat, view, viewer);
1161   }
1162   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1163     PetscCall(PetscViewerASCIIPushTab(viewer));
1164     PetscUseTypeMethod(mat, viewnative, viewer);
1165     PetscCall(PetscViewerASCIIPopTab(viewer));
1166   } else if (mat->ops->view) {
1167     PetscCall(PetscViewerASCIIPushTab(viewer));
1168     PetscUseTypeMethod(mat, view, viewer);
1169     PetscCall(PetscViewerASCIIPopTab(viewer));
1170   }
1171   if (isascii) {
1172     PetscCall(PetscViewerGetFormat(viewer, &format));
1173     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1174   }
1175   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1176 #if !defined(PETSC_HAVE_THREADSAFETY)
1177   insidematview--;
1178 #endif
1179   PetscFunctionReturn(PETSC_SUCCESS);
1180 }
1181 
1182 #if defined(PETSC_USE_DEBUG)
1183   #include <../src/sys/totalview/tv_data_display.h>
1184 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1185 {
1186   TV_add_row("Local rows", "int", &mat->rmap->n);
1187   TV_add_row("Local columns", "int", &mat->cmap->n);
1188   TV_add_row("Global rows", "int", &mat->rmap->N);
1189   TV_add_row("Global columns", "int", &mat->cmap->N);
1190   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1191   return TV_format_OK;
1192 }
1193 #endif
1194 
1195 /*@C
1196   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1197   with `MatView()`.  The matrix format is determined from the options database.
1198   Generates a parallel MPI matrix if the communicator has more than one
1199   processor.  The default matrix type is `MATAIJ`.
1200 
1201   Collective
1202 
1203   Input Parameters:
1204 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1205             or some related function before a call to `MatLoad()`
1206 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1207 
1208   Options Database Key:
1209 . -matload_block_size <bs> - set block size
1210 
1211   Level: beginner
1212 
1213   Notes:
1214   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1215   `Mat` before calling this routine if you wish to set it from the options database.
1216 
1217   `MatLoad()` automatically loads into the options database any options
1218   given in the file filename.info where filename is the name of the file
1219   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1220   file will be ignored if you use the -viewer_binary_skip_info option.
1221 
1222   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1223   sets the default matrix type AIJ and sets the local and global sizes.
1224   If type and/or size is already set, then the same are used.
1225 
1226   In parallel, each processor can load a subset of rows (or the
1227   entire matrix).  This routine is especially useful when a large
1228   matrix is stored on disk and only part of it is desired on each
1229   processor.  For example, a parallel solver may access only some of
1230   the rows from each processor.  The algorithm used here reads
1231   relatively small blocks of data rather than reading the entire
1232   matrix and then subsetting it.
1233 
1234   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1235   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1236   or the sequence like
1237 .vb
1238     `PetscViewer` v;
1239     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1240     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1241     `PetscViewerSetFromOptions`(v);
1242     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1243     `PetscViewerFileSetName`(v,"datafile");
1244 .ve
1245   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1246 $ -viewer_type {binary, hdf5}
1247 
1248   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1249   and src/mat/tutorials/ex10.c with the second approach.
1250 
1251   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1252   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1253   Multiple objects, both matrices and vectors, can be stored within the same file.
1254   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1255 
1256   Most users should not need to know the details of the binary storage
1257   format, since `MatLoad()` and `MatView()` completely hide these details.
1258   But for anyone who is interested, the standard binary matrix storage
1259   format is
1260 
1261 .vb
1262     PetscInt    MAT_FILE_CLASSID
1263     PetscInt    number of rows
1264     PetscInt    number of columns
1265     PetscInt    total number of nonzeros
1266     PetscInt    *number nonzeros in each row
1267     PetscInt    *column indices of all nonzeros (starting index is zero)
1268     PetscScalar *values of all nonzeros
1269 .ve
1270   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1271   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
1272   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1273 
1274   PETSc automatically does the byte swapping for
1275   machines that store the bytes reversed. Thus if you write your own binary
1276   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1277   and `PetscBinaryWrite()` to see how this may be done.
1278 
1279   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1280   Each processor's chunk is loaded independently by its owning MPI process.
1281   Multiple objects, both matrices and vectors, can be stored within the same file.
1282   They are looked up by their PetscObject name.
1283 
1284   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1285   by default the same structure and naming of the AIJ arrays and column count
1286   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1287 $    save example.mat A b -v7.3
1288   can be directly read by this routine (see Reference 1 for details).
1289 
1290   Depending on your MATLAB version, this format might be a default,
1291   otherwise you can set it as default in Preferences.
1292 
1293   Unless -nocompression flag is used to save the file in MATLAB,
1294   PETSc must be configured with ZLIB package.
1295 
1296   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1297 
1298   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1299 
1300   Corresponding `MatView()` is not yet implemented.
1301 
1302   The loaded matrix is actually a transpose of the original one in MATLAB,
1303   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1304   With this format, matrix is automatically transposed by PETSc,
1305   unless the matrix is marked as SPD or symmetric
1306   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1307 
1308   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1309 
1310 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1311  @*/
1312 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1313 {
1314   PetscBool flg;
1315 
1316   PetscFunctionBegin;
1317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1318   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1319 
1320   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1321 
1322   flg = PETSC_FALSE;
1323   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1324   if (flg) {
1325     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1326     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1327   }
1328   flg = PETSC_FALSE;
1329   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1330   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1331 
1332   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1333   PetscUseTypeMethod(mat, load, viewer);
1334   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1339 {
1340   Mat_Redundant *redund = *redundant;
1341 
1342   PetscFunctionBegin;
1343   if (redund) {
1344     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1345       PetscCall(ISDestroy(&redund->isrow));
1346       PetscCall(ISDestroy(&redund->iscol));
1347       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1348     } else {
1349       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1350       PetscCall(PetscFree(redund->sbuf_j));
1351       PetscCall(PetscFree(redund->sbuf_a));
1352       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1353         PetscCall(PetscFree(redund->rbuf_j[i]));
1354         PetscCall(PetscFree(redund->rbuf_a[i]));
1355       }
1356       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1357     }
1358 
1359     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1360     PetscCall(PetscFree(redund));
1361   }
1362   PetscFunctionReturn(PETSC_SUCCESS);
1363 }
1364 
1365 /*@C
1366   MatDestroy - Frees space taken by a matrix.
1367 
1368   Collective
1369 
1370   Input Parameter:
1371 . A - the matrix
1372 
1373   Level: beginner
1374 
1375   Developer Note:
1376   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1377   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1378   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1379   if changes are needed here.
1380 
1381 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1382 @*/
1383 PetscErrorCode MatDestroy(Mat *A)
1384 {
1385   PetscFunctionBegin;
1386   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1387   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1388   if (--((PetscObject)(*A))->refct > 0) {
1389     *A = NULL;
1390     PetscFunctionReturn(PETSC_SUCCESS);
1391   }
1392 
1393   /* if memory was published with SAWs then destroy it */
1394   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1395   PetscTryTypeMethod((*A), destroy);
1396 
1397   PetscCall(PetscFree((*A)->factorprefix));
1398   PetscCall(PetscFree((*A)->defaultvectype));
1399   PetscCall(PetscFree((*A)->defaultrandtype));
1400   PetscCall(PetscFree((*A)->bsizes));
1401   PetscCall(PetscFree((*A)->solvertype));
1402   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1403   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1404   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1405   PetscCall(MatProductClear(*A));
1406   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1407   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1408   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1409   PetscCall(MatDestroy(&(*A)->schur));
1410   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1411   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1412   PetscCall(PetscHeaderDestroy(A));
1413   PetscFunctionReturn(PETSC_SUCCESS);
1414 }
1415 
1416 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1417 /*@C
1418   MatSetValues - Inserts or adds a block of values into a matrix.
1419   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1420   MUST be called after all calls to `MatSetValues()` have been completed.
1421 
1422   Not Collective
1423 
1424   Input Parameters:
1425 + mat  - the matrix
1426 . v    - a logically two-dimensional array of values
1427 . m    - the number of rows
1428 . idxm - the global indices of the rows
1429 . n    - the number of columns
1430 . idxn - the global indices of the columns
1431 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1432 
1433   Level: beginner
1434 
1435   Notes:
1436   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1437 
1438   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1439   options cannot be mixed without intervening calls to the assembly
1440   routines.
1441 
1442   `MatSetValues()` uses 0-based row and column numbers in Fortran
1443   as well as in C.
1444 
1445   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1446   simply ignored. This allows easily inserting element stiffness matrices
1447   with homogeneous Dirichlet boundary conditions that you don't want represented
1448   in the matrix.
1449 
1450   Efficiency Alert:
1451   The routine `MatSetValuesBlocked()` may offer much better efficiency
1452   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1453 
1454   Developer Note:
1455   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1456   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1457 
1458 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1459           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1460 @*/
1461 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1462 {
1463   PetscFunctionBeginHot;
1464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1465   PetscValidType(mat, 1);
1466   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1467   PetscAssertPointer(idxm, 3);
1468   PetscAssertPointer(idxn, 5);
1469   MatCheckPreallocated(mat, 1);
1470 
1471   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1472   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1473 
1474   if (PetscDefined(USE_DEBUG)) {
1475     PetscInt i, j;
1476 
1477     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1478     for (i = 0; i < m; i++) {
1479       for (j = 0; j < n; j++) {
1480         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1481 #if defined(PETSC_USE_COMPLEX)
1482           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]);
1483 #else
1484           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]);
1485 #endif
1486       }
1487     }
1488     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);
1489     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);
1490   }
1491 
1492   if (mat->assembled) {
1493     mat->was_assembled = PETSC_TRUE;
1494     mat->assembled     = PETSC_FALSE;
1495   }
1496   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1497   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1498   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1503 /*@C
1504   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1505   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1506   MUST be called after all calls to `MatSetValues()` have been completed.
1507 
1508   Not Collective
1509 
1510   Input Parameters:
1511 + mat  - the matrix
1512 . v    - a logically two-dimensional array of values
1513 . ism  - the rows to provide
1514 . isn  - the columns to provide
1515 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1516 
1517   Level: beginner
1518 
1519   Notes:
1520   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1521 
1522   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1523   options cannot be mixed without intervening calls to the assembly
1524   routines.
1525 
1526   `MatSetValues()` uses 0-based row and column numbers in Fortran
1527   as well as in C.
1528 
1529   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1530   simply ignored. This allows easily inserting element stiffness matrices
1531   with homogeneous Dirichlet boundary conditions that you don't want represented
1532   in the matrix.
1533 
1534   Efficiency Alert:
1535   The routine `MatSetValuesBlocked()` may offer much better efficiency
1536   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1537 
1538   This is currently not optimized for any particular `ISType`
1539 
1540   Developer Note:
1541   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1542   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1543 
1544 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1545           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1546 @*/
1547 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1548 {
1549   PetscInt        m, n;
1550   const PetscInt *rows, *cols;
1551 
1552   PetscFunctionBeginHot;
1553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1554   PetscCall(ISGetIndices(ism, &rows));
1555   PetscCall(ISGetIndices(isn, &cols));
1556   PetscCall(ISGetLocalSize(ism, &m));
1557   PetscCall(ISGetLocalSize(isn, &n));
1558   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1559   PetscCall(ISRestoreIndices(ism, &rows));
1560   PetscCall(ISRestoreIndices(isn, &cols));
1561   PetscFunctionReturn(PETSC_SUCCESS);
1562 }
1563 
1564 /*@
1565   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1566   values into a matrix
1567 
1568   Not Collective
1569 
1570   Input Parameters:
1571 + mat - the matrix
1572 . row - the (block) row to set
1573 - v   - a logically two-dimensional array of values
1574 
1575   Level: intermediate
1576 
1577   Notes:
1578   The values, `v`, are column-oriented (for the block version) and sorted
1579 
1580   All the nonzero values in `row` must be provided
1581 
1582   The matrix must have previously had its column indices set, likely by having been assembled.
1583 
1584   `row` must belong to this MPI process
1585 
1586 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1587           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1588 @*/
1589 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1590 {
1591   PetscInt globalrow;
1592 
1593   PetscFunctionBegin;
1594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1595   PetscValidType(mat, 1);
1596   PetscAssertPointer(v, 3);
1597   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1598   PetscCall(MatSetValuesRow(mat, globalrow, v));
1599   PetscFunctionReturn(PETSC_SUCCESS);
1600 }
1601 
1602 /*@
1603   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1604   values into a matrix
1605 
1606   Not Collective
1607 
1608   Input Parameters:
1609 + mat - the matrix
1610 . row - the (block) row to set
1611 - 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
1612 
1613   Level: advanced
1614 
1615   Notes:
1616   The values, `v`, are column-oriented for the block version.
1617 
1618   All the nonzeros in `row` must be provided
1619 
1620   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1621 
1622   `row` must belong to this process
1623 
1624 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1625           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1626 @*/
1627 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1628 {
1629   PetscFunctionBeginHot;
1630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1631   PetscValidType(mat, 1);
1632   MatCheckPreallocated(mat, 1);
1633   PetscAssertPointer(v, 3);
1634   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1635   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1636   mat->insertmode = INSERT_VALUES;
1637 
1638   if (mat->assembled) {
1639     mat->was_assembled = PETSC_TRUE;
1640     mat->assembled     = PETSC_FALSE;
1641   }
1642   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1643   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1644   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1645   PetscFunctionReturn(PETSC_SUCCESS);
1646 }
1647 
1648 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1649 /*@
1650   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1651   Using structured grid indexing
1652 
1653   Not Collective
1654 
1655   Input Parameters:
1656 + mat  - the matrix
1657 . m    - number of rows being entered
1658 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1659 . n    - number of columns being entered
1660 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1661 . v    - a logically two-dimensional array of values
1662 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1663 
1664   Level: beginner
1665 
1666   Notes:
1667   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1668 
1669   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1670   options cannot be mixed without intervening calls to the assembly
1671   routines.
1672 
1673   The grid coordinates are across the entire grid, not just the local portion
1674 
1675   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1676   as well as in C.
1677 
1678   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1679 
1680   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1681   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1682 
1683   The columns and rows in the stencil passed in MUST be contained within the
1684   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1685   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1686   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1687   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1688 
1689   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1690   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1691   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1692   `DM_BOUNDARY_PERIODIC` boundary type.
1693 
1694   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
1695   a single value per point) you can skip filling those indices.
1696 
1697   Inspired by the structured grid interface to the HYPRE package
1698   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1699 
1700   Efficiency Alert:
1701   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1702   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1703 
1704   Fortran Note:
1705   `idxm` and `idxn` should be declared as
1706 $     MatStencil idxm(4,m),idxn(4,n)
1707   and the values inserted using
1708 .vb
1709     idxm(MatStencil_i,1) = i
1710     idxm(MatStencil_j,1) = j
1711     idxm(MatStencil_k,1) = k
1712     idxm(MatStencil_c,1) = c
1713     etc
1714 .ve
1715 
1716 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1717           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1718 @*/
1719 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1720 {
1721   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1722   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1723   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1724 
1725   PetscFunctionBegin;
1726   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1728   PetscValidType(mat, 1);
1729   PetscAssertPointer(idxm, 3);
1730   PetscAssertPointer(idxn, 5);
1731 
1732   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1733     jdxm = buf;
1734     jdxn = buf + m;
1735   } else {
1736     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1737     jdxm = bufm;
1738     jdxn = bufn;
1739   }
1740   for (i = 0; i < m; i++) {
1741     for (j = 0; j < 3 - sdim; j++) dxm++;
1742     tmp = *dxm++ - starts[0];
1743     for (j = 0; j < dim - 1; j++) {
1744       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1745       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1746     }
1747     if (mat->stencil.noc) dxm++;
1748     jdxm[i] = tmp;
1749   }
1750   for (i = 0; i < n; i++) {
1751     for (j = 0; j < 3 - sdim; j++) dxn++;
1752     tmp = *dxn++ - starts[0];
1753     for (j = 0; j < dim - 1; j++) {
1754       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1755       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1756     }
1757     if (mat->stencil.noc) dxn++;
1758     jdxn[i] = tmp;
1759   }
1760   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1761   PetscCall(PetscFree2(bufm, bufn));
1762   PetscFunctionReturn(PETSC_SUCCESS);
1763 }
1764 
1765 /*@
1766   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1767   Using structured grid indexing
1768 
1769   Not Collective
1770 
1771   Input Parameters:
1772 + mat  - the matrix
1773 . m    - number of rows being entered
1774 . idxm - grid coordinates for matrix rows being entered
1775 . n    - number of columns being entered
1776 . idxn - grid coordinates for matrix columns being entered
1777 . v    - a logically two-dimensional array of values
1778 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1779 
1780   Level: beginner
1781 
1782   Notes:
1783   By default the values, `v`, are row-oriented and unsorted.
1784   See `MatSetOption()` for other options.
1785 
1786   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1787   options cannot be mixed without intervening calls to the assembly
1788   routines.
1789 
1790   The grid coordinates are across the entire grid, not just the local portion
1791 
1792   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1793   as well as in C.
1794 
1795   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1796 
1797   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1798   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1799 
1800   The columns and rows in the stencil passed in MUST be contained within the
1801   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1802   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1803   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1804   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1805 
1806   Negative indices may be passed in idxm and idxn, these rows and columns are
1807   simply ignored. This allows easily inserting element stiffness matrices
1808   with homogeneous Dirichlet boundary conditions that you don't want represented
1809   in the matrix.
1810 
1811   Inspired by the structured grid interface to the HYPRE package
1812   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1813 
1814   Fortran Note:
1815   `idxm` and `idxn` should be declared as
1816 $     MatStencil idxm(4,m),idxn(4,n)
1817   and the values inserted using
1818 .vb
1819     idxm(MatStencil_i,1) = i
1820     idxm(MatStencil_j,1) = j
1821     idxm(MatStencil_k,1) = k
1822    etc
1823 .ve
1824 
1825 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1826           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1827           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1828 @*/
1829 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1830 {
1831   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1832   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1833   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1834 
1835   PetscFunctionBegin;
1836   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1838   PetscValidType(mat, 1);
1839   PetscAssertPointer(idxm, 3);
1840   PetscAssertPointer(idxn, 5);
1841   PetscAssertPointer(v, 6);
1842 
1843   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1844     jdxm = buf;
1845     jdxn = buf + m;
1846   } else {
1847     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1848     jdxm = bufm;
1849     jdxn = bufn;
1850   }
1851   for (i = 0; i < m; i++) {
1852     for (j = 0; j < 3 - sdim; j++) dxm++;
1853     tmp = *dxm++ - starts[0];
1854     for (j = 0; j < sdim - 1; j++) {
1855       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1856       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1857     }
1858     dxm++;
1859     jdxm[i] = tmp;
1860   }
1861   for (i = 0; i < n; i++) {
1862     for (j = 0; j < 3 - sdim; j++) dxn++;
1863     tmp = *dxn++ - starts[0];
1864     for (j = 0; j < sdim - 1; j++) {
1865       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1866       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1867     }
1868     dxn++;
1869     jdxn[i] = tmp;
1870   }
1871   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1872   PetscCall(PetscFree2(bufm, bufn));
1873   PetscFunctionReturn(PETSC_SUCCESS);
1874 }
1875 
1876 /*@
1877   MatSetStencil - Sets the grid information for setting values into a matrix via
1878   `MatSetValuesStencil()`
1879 
1880   Not Collective
1881 
1882   Input Parameters:
1883 + mat    - the matrix
1884 . dim    - dimension of the grid 1, 2, or 3
1885 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1886 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1887 - dof    - number of degrees of freedom per node
1888 
1889   Level: beginner
1890 
1891   Notes:
1892   Inspired by the structured grid interface to the HYPRE package
1893   (www.llnl.gov/CASC/hyper)
1894 
1895   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1896   user.
1897 
1898 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1899           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1900 @*/
1901 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1902 {
1903   PetscFunctionBegin;
1904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1905   PetscAssertPointer(dims, 3);
1906   PetscAssertPointer(starts, 4);
1907 
1908   mat->stencil.dim = dim + (dof > 1);
1909   for (PetscInt i = 0; i < dim; i++) {
1910     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1911     mat->stencil.starts[i] = starts[dim - i - 1];
1912   }
1913   mat->stencil.dims[dim]   = dof;
1914   mat->stencil.starts[dim] = 0;
1915   mat->stencil.noc         = (PetscBool)(dof == 1);
1916   PetscFunctionReturn(PETSC_SUCCESS);
1917 }
1918 
1919 /*@C
1920   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1921 
1922   Not Collective
1923 
1924   Input Parameters:
1925 + mat  - the matrix
1926 . v    - a logically two-dimensional array of values
1927 . m    - the number of block rows
1928 . idxm - the global block indices
1929 . n    - the number of block columns
1930 . idxn - the global block indices
1931 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1932 
1933   Level: intermediate
1934 
1935   Notes:
1936   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1937   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1938 
1939   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1940   NOT the total number of rows/columns; for example, if the block size is 2 and
1941   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1942   The values in idxm would be 1 2; that is the first index for each block divided by
1943   the block size.
1944 
1945   You must call `MatSetBlockSize()` when constructing this matrix (before
1946   preallocating it).
1947 
1948   By default the values, `v`, are row-oriented, so the layout of
1949   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1950 
1951   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1952   options cannot be mixed without intervening calls to the assembly
1953   routines.
1954 
1955   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1956   as well as in C.
1957 
1958   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1959   simply ignored. This allows easily inserting element stiffness matrices
1960   with homogeneous Dirichlet boundary conditions that you don't want represented
1961   in the matrix.
1962 
1963   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1964   internal searching must be done to determine where to place the
1965   data in the matrix storage space.  By instead inserting blocks of
1966   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1967   reduced.
1968 
1969   Example:
1970 .vb
1971    Suppose m=n=2 and block size(bs) = 2 The array is
1972 
1973    1  2  | 3  4
1974    5  6  | 7  8
1975    - - - | - - -
1976    9  10 | 11 12
1977    13 14 | 15 16
1978 
1979    v[] should be passed in like
1980    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1981 
1982   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1983    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1984 .ve
1985 
1986 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1987 @*/
1988 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1989 {
1990   PetscFunctionBeginHot;
1991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1992   PetscValidType(mat, 1);
1993   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1994   PetscAssertPointer(idxm, 3);
1995   PetscAssertPointer(idxn, 5);
1996   MatCheckPreallocated(mat, 1);
1997   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1998   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1999   if (PetscDefined(USE_DEBUG)) {
2000     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2001     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2002   }
2003   if (PetscDefined(USE_DEBUG)) {
2004     PetscInt rbs, cbs, M, N, i;
2005     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2006     PetscCall(MatGetSize(mat, &M, &N));
2007     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);
2008     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);
2009   }
2010   if (mat->assembled) {
2011     mat->was_assembled = PETSC_TRUE;
2012     mat->assembled     = PETSC_FALSE;
2013   }
2014   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2015   if (mat->ops->setvaluesblocked) {
2016     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2017   } else {
2018     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2019     PetscInt i, j, bs, cbs;
2020 
2021     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2022     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2023       iidxm = buf;
2024       iidxn = buf + m * bs;
2025     } else {
2026       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2027       iidxm = bufr;
2028       iidxn = bufc;
2029     }
2030     for (i = 0; i < m; i++) {
2031       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2032     }
2033     if (m != n || bs != cbs || idxm != idxn) {
2034       for (i = 0; i < n; i++) {
2035         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2036       }
2037     } else iidxn = iidxm;
2038     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2039     PetscCall(PetscFree2(bufr, bufc));
2040   }
2041   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2042   PetscFunctionReturn(PETSC_SUCCESS);
2043 }
2044 
2045 /*@C
2046   MatGetValues - Gets a block of local values from a matrix.
2047 
2048   Not Collective; can only return values that are owned by the give process
2049 
2050   Input Parameters:
2051 + mat  - the matrix
2052 . v    - a logically two-dimensional array for storing the values
2053 . m    - the number of rows
2054 . idxm - the  global indices of the rows
2055 . n    - the number of columns
2056 - idxn - the global indices of the columns
2057 
2058   Level: advanced
2059 
2060   Notes:
2061   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2062   The values, `v`, are then returned in a row-oriented format,
2063   analogous to that used by default in `MatSetValues()`.
2064 
2065   `MatGetValues()` uses 0-based row and column numbers in
2066   Fortran as well as in C.
2067 
2068   `MatGetValues()` requires that the matrix has been assembled
2069   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2070   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2071   without intermediate matrix assembly.
2072 
2073   Negative row or column indices will be ignored and those locations in `v` will be
2074   left unchanged.
2075 
2076   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2077   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2078   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2079 
2080 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2081 @*/
2082 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2083 {
2084   PetscFunctionBegin;
2085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2086   PetscValidType(mat, 1);
2087   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2088   PetscAssertPointer(idxm, 3);
2089   PetscAssertPointer(idxn, 5);
2090   PetscAssertPointer(v, 6);
2091   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2092   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2093   MatCheckPreallocated(mat, 1);
2094 
2095   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2096   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2097   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2098   PetscFunctionReturn(PETSC_SUCCESS);
2099 }
2100 
2101 /*@C
2102   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2103   defined previously by `MatSetLocalToGlobalMapping()`
2104 
2105   Not Collective
2106 
2107   Input Parameters:
2108 + mat  - the matrix
2109 . nrow - number of rows
2110 . irow - the row local indices
2111 . ncol - number of columns
2112 - icol - the column local indices
2113 
2114   Output Parameter:
2115 . y - a logically two-dimensional array of values
2116 
2117   Level: advanced
2118 
2119   Notes:
2120   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2121 
2122   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,
2123   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2124   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2125   with `MatSetLocalToGlobalMapping()`.
2126 
2127   Developer Note:
2128   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2129   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2130 
2131 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2132           `MatSetValuesLocal()`, `MatGetValues()`
2133 @*/
2134 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2135 {
2136   PetscFunctionBeginHot;
2137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2138   PetscValidType(mat, 1);
2139   MatCheckPreallocated(mat, 1);
2140   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2141   PetscAssertPointer(irow, 3);
2142   PetscAssertPointer(icol, 5);
2143   if (PetscDefined(USE_DEBUG)) {
2144     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2145     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2146   }
2147   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2148   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2149   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2150   else {
2151     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2152     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2153       irowm = buf;
2154       icolm = buf + nrow;
2155     } else {
2156       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2157       irowm = bufr;
2158       icolm = bufc;
2159     }
2160     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2161     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2162     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2163     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2164     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2165     PetscCall(PetscFree2(bufr, bufc));
2166   }
2167   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2168   PetscFunctionReturn(PETSC_SUCCESS);
2169 }
2170 
2171 /*@
2172   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2173   the same size. Currently, this can only be called once and creates the given matrix.
2174 
2175   Not Collective
2176 
2177   Input Parameters:
2178 + mat  - the matrix
2179 . nb   - the number of blocks
2180 . bs   - the number of rows (and columns) in each block
2181 . rows - a concatenation of the rows for each block
2182 - v    - a concatenation of logically two-dimensional arrays of values
2183 
2184   Level: advanced
2185 
2186   Notes:
2187   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2188 
2189   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2190 
2191 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2192           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2193 @*/
2194 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2195 {
2196   PetscFunctionBegin;
2197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2198   PetscValidType(mat, 1);
2199   PetscAssertPointer(rows, 4);
2200   PetscAssertPointer(v, 5);
2201   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2202 
2203   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2204   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2205   else {
2206     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2207   }
2208   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2209   PetscFunctionReturn(PETSC_SUCCESS);
2210 }
2211 
2212 /*@
2213   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2214   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2215   using a local (per-processor) numbering.
2216 
2217   Not Collective
2218 
2219   Input Parameters:
2220 + x        - the matrix
2221 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2222 - cmapping - column mapping
2223 
2224   Level: intermediate
2225 
2226   Note:
2227   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2228 
2229 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2230 @*/
2231 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2232 {
2233   PetscFunctionBegin;
2234   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2235   PetscValidType(x, 1);
2236   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2237   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2238   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2239   else {
2240     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2241     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2242   }
2243   PetscFunctionReturn(PETSC_SUCCESS);
2244 }
2245 
2246 /*@
2247   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2248 
2249   Not Collective
2250 
2251   Input Parameter:
2252 . A - the matrix
2253 
2254   Output Parameters:
2255 + rmapping - row mapping
2256 - cmapping - column mapping
2257 
2258   Level: advanced
2259 
2260 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2261 @*/
2262 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2263 {
2264   PetscFunctionBegin;
2265   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2266   PetscValidType(A, 1);
2267   if (rmapping) {
2268     PetscAssertPointer(rmapping, 2);
2269     *rmapping = A->rmap->mapping;
2270   }
2271   if (cmapping) {
2272     PetscAssertPointer(cmapping, 3);
2273     *cmapping = A->cmap->mapping;
2274   }
2275   PetscFunctionReturn(PETSC_SUCCESS);
2276 }
2277 
2278 /*@
2279   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2280 
2281   Logically Collective
2282 
2283   Input Parameters:
2284 + A    - the matrix
2285 . rmap - row layout
2286 - cmap - column layout
2287 
2288   Level: advanced
2289 
2290   Note:
2291   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2292 
2293 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2294 @*/
2295 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2296 {
2297   PetscFunctionBegin;
2298   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2299   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2300   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2301   PetscFunctionReturn(PETSC_SUCCESS);
2302 }
2303 
2304 /*@
2305   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2306 
2307   Not Collective
2308 
2309   Input Parameter:
2310 . A - the matrix
2311 
2312   Output Parameters:
2313 + rmap - row layout
2314 - cmap - column layout
2315 
2316   Level: advanced
2317 
2318 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2319 @*/
2320 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2321 {
2322   PetscFunctionBegin;
2323   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2324   PetscValidType(A, 1);
2325   if (rmap) {
2326     PetscAssertPointer(rmap, 2);
2327     *rmap = A->rmap;
2328   }
2329   if (cmap) {
2330     PetscAssertPointer(cmap, 3);
2331     *cmap = A->cmap;
2332   }
2333   PetscFunctionReturn(PETSC_SUCCESS);
2334 }
2335 
2336 /*@C
2337   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2338   using a local numbering of the rows and columns.
2339 
2340   Not Collective
2341 
2342   Input Parameters:
2343 + mat  - the matrix
2344 . nrow - number of rows
2345 . irow - the row local indices
2346 . ncol - number of columns
2347 . icol - the column local indices
2348 . y    - a logically two-dimensional array of values
2349 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2350 
2351   Level: intermediate
2352 
2353   Notes:
2354   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2355 
2356   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2357   options cannot be mixed without intervening calls to the assembly
2358   routines.
2359 
2360   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2361   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2362 
2363   Developer Note:
2364   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2365   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2366 
2367 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2368           `MatGetValuesLocal()`
2369 @*/
2370 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2371 {
2372   PetscFunctionBeginHot;
2373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2374   PetscValidType(mat, 1);
2375   MatCheckPreallocated(mat, 1);
2376   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2377   PetscAssertPointer(irow, 3);
2378   PetscAssertPointer(icol, 5);
2379   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2380   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2381   if (PetscDefined(USE_DEBUG)) {
2382     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2383     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2384   }
2385 
2386   if (mat->assembled) {
2387     mat->was_assembled = PETSC_TRUE;
2388     mat->assembled     = PETSC_FALSE;
2389   }
2390   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2391   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2392   else {
2393     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2394     const PetscInt *irowm, *icolm;
2395 
2396     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2397       bufr  = buf;
2398       bufc  = buf + nrow;
2399       irowm = bufr;
2400       icolm = bufc;
2401     } else {
2402       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2403       irowm = bufr;
2404       icolm = bufc;
2405     }
2406     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2407     else irowm = irow;
2408     if (mat->cmap->mapping) {
2409       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2410         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2411       } else icolm = irowm;
2412     } else icolm = icol;
2413     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2414     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2415   }
2416   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2417   PetscFunctionReturn(PETSC_SUCCESS);
2418 }
2419 
2420 /*@C
2421   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2422   using a local ordering of the nodes a block at a time.
2423 
2424   Not Collective
2425 
2426   Input Parameters:
2427 + mat  - the matrix
2428 . nrow - number of rows
2429 . irow - the row local indices
2430 . ncol - number of columns
2431 . icol - the column local indices
2432 . y    - a logically two-dimensional array of values
2433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2434 
2435   Level: intermediate
2436 
2437   Notes:
2438   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2439   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2440 
2441   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2442   options cannot be mixed without intervening calls to the assembly
2443   routines.
2444 
2445   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2446   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2447 
2448   Developer Note:
2449   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2450   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2451 
2452 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2453           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2454 @*/
2455 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2456 {
2457   PetscFunctionBeginHot;
2458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2459   PetscValidType(mat, 1);
2460   MatCheckPreallocated(mat, 1);
2461   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2462   PetscAssertPointer(irow, 3);
2463   PetscAssertPointer(icol, 5);
2464   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2465   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2466   if (PetscDefined(USE_DEBUG)) {
2467     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2468     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);
2469   }
2470 
2471   if (mat->assembled) {
2472     mat->was_assembled = PETSC_TRUE;
2473     mat->assembled     = PETSC_FALSE;
2474   }
2475   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2476     PetscInt irbs, rbs;
2477     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2478     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2479     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2480   }
2481   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2482     PetscInt icbs, cbs;
2483     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2484     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2485     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2486   }
2487   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2488   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2489   else {
2490     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2491     const PetscInt *irowm, *icolm;
2492 
2493     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2494       bufr  = buf;
2495       bufc  = buf + nrow;
2496       irowm = bufr;
2497       icolm = bufc;
2498     } else {
2499       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2500       irowm = bufr;
2501       icolm = bufc;
2502     }
2503     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2504     else irowm = irow;
2505     if (mat->cmap->mapping) {
2506       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2507         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2508       } else icolm = irowm;
2509     } else icolm = icol;
2510     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2511     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2512   }
2513   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2514   PetscFunctionReturn(PETSC_SUCCESS);
2515 }
2516 
2517 /*@
2518   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2519 
2520   Collective
2521 
2522   Input Parameters:
2523 + mat - the matrix
2524 - x   - the vector to be multiplied
2525 
2526   Output Parameter:
2527 . y - the result
2528 
2529   Level: developer
2530 
2531   Note:
2532   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2533   call `MatMultDiagonalBlock`(A,y,y).
2534 
2535 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2536 @*/
2537 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2538 {
2539   PetscFunctionBegin;
2540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2541   PetscValidType(mat, 1);
2542   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2543   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2544 
2545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2547   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2548   MatCheckPreallocated(mat, 1);
2549 
2550   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2551   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2552   PetscFunctionReturn(PETSC_SUCCESS);
2553 }
2554 
2555 /*@
2556   MatMult - Computes the matrix-vector product, $y = Ax$.
2557 
2558   Neighbor-wise Collective
2559 
2560   Input Parameters:
2561 + mat - the matrix
2562 - x   - the vector to be multiplied
2563 
2564   Output Parameter:
2565 . y - the result
2566 
2567   Level: beginner
2568 
2569   Note:
2570   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2571   call `MatMult`(A,y,y).
2572 
2573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2574 @*/
2575 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2576 {
2577   PetscFunctionBegin;
2578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2579   PetscValidType(mat, 1);
2580   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2581   VecCheckAssembled(x);
2582   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2583   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2584   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2585   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2586   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);
2587   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);
2588   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);
2589   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);
2590   PetscCall(VecSetErrorIfLocked(y, 3));
2591   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2592   MatCheckPreallocated(mat, 1);
2593 
2594   PetscCall(VecLockReadPush(x));
2595   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2596   PetscUseTypeMethod(mat, mult, x, y);
2597   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2598   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2599   PetscCall(VecLockReadPop(x));
2600   PetscFunctionReturn(PETSC_SUCCESS);
2601 }
2602 
2603 /*@
2604   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2605 
2606   Neighbor-wise Collective
2607 
2608   Input Parameters:
2609 + mat - the matrix
2610 - x   - the vector to be multiplied
2611 
2612   Output Parameter:
2613 . y - the result
2614 
2615   Level: beginner
2616 
2617   Notes:
2618   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2619   call `MatMultTranspose`(A,y,y).
2620 
2621   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2622   use `MatMultHermitianTranspose()`
2623 
2624 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2625 @*/
2626 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2627 {
2628   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2629 
2630   PetscFunctionBegin;
2631   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2632   PetscValidType(mat, 1);
2633   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2634   VecCheckAssembled(x);
2635   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2636 
2637   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2638   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2639   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2640   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);
2641   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);
2642   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);
2643   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);
2644   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2645   MatCheckPreallocated(mat, 1);
2646 
2647   if (!mat->ops->multtranspose) {
2648     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2649     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);
2650   } else op = mat->ops->multtranspose;
2651   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2652   PetscCall(VecLockReadPush(x));
2653   PetscCall((*op)(mat, x, y));
2654   PetscCall(VecLockReadPop(x));
2655   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2658   PetscFunctionReturn(PETSC_SUCCESS);
2659 }
2660 
2661 /*@
2662   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2663 
2664   Neighbor-wise Collective
2665 
2666   Input Parameters:
2667 + mat - the matrix
2668 - x   - the vector to be multiplied
2669 
2670   Output Parameter:
2671 . y - the result
2672 
2673   Level: beginner
2674 
2675   Notes:
2676   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2677   call `MatMultHermitianTranspose`(A,y,y).
2678 
2679   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2680 
2681   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2682 
2683 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2684 @*/
2685 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2686 {
2687   PetscFunctionBegin;
2688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2689   PetscValidType(mat, 1);
2690   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2691   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2692 
2693   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2695   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2696   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);
2697   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);
2698   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);
2699   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);
2700   MatCheckPreallocated(mat, 1);
2701 
2702   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2703 #if defined(PETSC_USE_COMPLEX)
2704   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2705     PetscCall(VecLockReadPush(x));
2706     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2707     else PetscUseTypeMethod(mat, mult, x, y);
2708     PetscCall(VecLockReadPop(x));
2709   } else {
2710     Vec w;
2711     PetscCall(VecDuplicate(x, &w));
2712     PetscCall(VecCopy(x, w));
2713     PetscCall(VecConjugate(w));
2714     PetscCall(MatMultTranspose(mat, w, y));
2715     PetscCall(VecDestroy(&w));
2716     PetscCall(VecConjugate(y));
2717   }
2718   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2719 #else
2720   PetscCall(MatMultTranspose(mat, x, y));
2721 #endif
2722   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2723   PetscFunctionReturn(PETSC_SUCCESS);
2724 }
2725 
2726 /*@
2727   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2728 
2729   Neighbor-wise Collective
2730 
2731   Input Parameters:
2732 + mat - the matrix
2733 . v1  - the vector to be multiplied by `mat`
2734 - v2  - the vector to be added to the result
2735 
2736   Output Parameter:
2737 . v3 - the result
2738 
2739   Level: beginner
2740 
2741   Note:
2742   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2743   call `MatMultAdd`(A,v1,v2,v1).
2744 
2745 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2746 @*/
2747 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2748 {
2749   PetscFunctionBegin;
2750   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2751   PetscValidType(mat, 1);
2752   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2753   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2754   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2755 
2756   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2757   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2758   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);
2759   /* 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);
2760      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); */
2761   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);
2762   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);
2763   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2764   MatCheckPreallocated(mat, 1);
2765 
2766   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2767   PetscCall(VecLockReadPush(v1));
2768   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2769   PetscCall(VecLockReadPop(v1));
2770   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2771   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2772   PetscFunctionReturn(PETSC_SUCCESS);
2773 }
2774 
2775 /*@
2776   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2777 
2778   Neighbor-wise Collective
2779 
2780   Input Parameters:
2781 + mat - the matrix
2782 . v1  - the vector to be multiplied by the transpose of the matrix
2783 - v2  - the vector to be added to the result
2784 
2785   Output Parameter:
2786 . v3 - the result
2787 
2788   Level: beginner
2789 
2790   Note:
2791   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2792   call `MatMultTransposeAdd`(A,v1,v2,v1).
2793 
2794 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2795 @*/
2796 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2797 {
2798   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2799 
2800   PetscFunctionBegin;
2801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2802   PetscValidType(mat, 1);
2803   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2804   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2805   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2806 
2807   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2808   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2809   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);
2810   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);
2811   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);
2812   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2813   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2814   MatCheckPreallocated(mat, 1);
2815 
2816   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2817   PetscCall(VecLockReadPush(v1));
2818   PetscCall((*op)(mat, v1, v2, v3));
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(PETSC_SUCCESS);
2823 }
2824 
2825 /*@
2826   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2827 
2828   Neighbor-wise Collective
2829 
2830   Input Parameters:
2831 + mat - the matrix
2832 . v1  - the vector to be multiplied by the Hermitian transpose
2833 - v2  - the vector to be added to the result
2834 
2835   Output Parameter:
2836 . v3 - the result
2837 
2838   Level: beginner
2839 
2840   Note:
2841   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2842   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2843 
2844 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2845 @*/
2846 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2847 {
2848   PetscFunctionBegin;
2849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2850   PetscValidType(mat, 1);
2851   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2852   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2853   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2854 
2855   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2856   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2857   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2858   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);
2859   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);
2860   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);
2861   MatCheckPreallocated(mat, 1);
2862 
2863   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2864   PetscCall(VecLockReadPush(v1));
2865   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2866   else {
2867     Vec w, z;
2868     PetscCall(VecDuplicate(v1, &w));
2869     PetscCall(VecCopy(v1, w));
2870     PetscCall(VecConjugate(w));
2871     PetscCall(VecDuplicate(v3, &z));
2872     PetscCall(MatMultTranspose(mat, w, z));
2873     PetscCall(VecDestroy(&w));
2874     PetscCall(VecConjugate(z));
2875     if (v2 != v3) {
2876       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2877     } else {
2878       PetscCall(VecAXPY(v3, 1.0, z));
2879     }
2880     PetscCall(VecDestroy(&z));
2881   }
2882   PetscCall(VecLockReadPop(v1));
2883   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2884   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2885   PetscFunctionReturn(PETSC_SUCCESS);
2886 }
2887 
2888 /*@C
2889   MatGetFactorType - gets the type of factorization a matrix is
2890 
2891   Not Collective
2892 
2893   Input Parameter:
2894 . mat - the matrix
2895 
2896   Output Parameter:
2897 . 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`
2898 
2899   Level: intermediate
2900 
2901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   PetscAssertPointer(t, 2);
2910   *t = mat->factortype;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915   MatSetFactorType - sets the type of factorization a matrix is
2916 
2917   Logically Collective
2918 
2919   Input Parameters:
2920 + mat - the matrix
2921 - 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`
2922 
2923   Level: intermediate
2924 
2925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2926           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2927 @*/
2928 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2929 {
2930   PetscFunctionBegin;
2931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2932   PetscValidType(mat, 1);
2933   mat->factortype = t;
2934   PetscFunctionReturn(PETSC_SUCCESS);
2935 }
2936 
2937 /*@C
2938   MatGetInfo - Returns information about matrix storage (number of
2939   nonzeros, memory, etc.).
2940 
2941   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2942 
2943   Input Parameters:
2944 + mat  - the matrix
2945 - 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)
2946 
2947   Output Parameter:
2948 . info - matrix information context
2949 
2950   Options Database Key:
2951 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2952 
2953   Notes:
2954   The `MatInfo` context contains a variety of matrix data, including
2955   number of nonzeros allocated and used, number of mallocs during
2956   matrix assembly, etc.  Additional information for factored matrices
2957   is provided (such as the fill ratio, number of mallocs during
2958   factorization, etc.).
2959 
2960   Example:
2961   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2962   data within the MatInfo context.  For example,
2963 .vb
2964       MatInfo info;
2965       Mat     A;
2966       double  mal, nz_a, nz_u;
2967 
2968       MatGetInfo(A, MAT_LOCAL, &info);
2969       mal  = info.mallocs;
2970       nz_a = info.nz_allocated;
2971 .ve
2972 
2973   Fortran users should declare info as a double precision
2974   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2975   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2976   a complete list of parameter names.
2977 .vb
2978       double  precision info(MAT_INFO_SIZE)
2979       double  precision mal, nz_a
2980       Mat     A
2981       integer ierr
2982 
2983       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2984       mal = info(MAT_INFO_MALLOCS)
2985       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2986 .ve
2987 
2988   Level: intermediate
2989 
2990   Developer Note:
2991   The Fortran interface is not autogenerated as the
2992   interface definition cannot be generated correctly [due to `MatInfo` argument]
2993 
2994 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2995 @*/
2996 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2997 {
2998   PetscFunctionBegin;
2999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3000   PetscValidType(mat, 1);
3001   PetscAssertPointer(info, 3);
3002   MatCheckPreallocated(mat, 1);
3003   PetscUseTypeMethod(mat, getinfo, flag, info);
3004   PetscFunctionReturn(PETSC_SUCCESS);
3005 }
3006 
3007 /*
3008    This is used by external packages where it is not easy to get the info from the actual
3009    matrix factorization.
3010 */
3011 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3012 {
3013   PetscFunctionBegin;
3014   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3015   PetscFunctionReturn(PETSC_SUCCESS);
3016 }
3017 
3018 /*@C
3019   MatLUFactor - Performs in-place LU factorization of matrix.
3020 
3021   Collective
3022 
3023   Input Parameters:
3024 + mat  - the matrix
3025 . row  - row permutation
3026 . col  - column permutation
3027 - info - options for factorization, includes
3028 .vb
3029           fill - expected fill as ratio of original fill.
3030           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3031                    Run with the option -info to determine an optimal value to use
3032 .ve
3033 
3034   Level: developer
3035 
3036   Notes:
3037   Most users should employ the `KSP` interface for linear solvers
3038   instead of working directly with matrix algebra routines such as this.
3039   See, e.g., `KSPCreate()`.
3040 
3041   This changes the state of the matrix to a factored matrix; it cannot be used
3042   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3043 
3044   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3045   when not using `KSP`.
3046 
3047   Developer Note:
3048   The Fortran interface is not autogenerated as the
3049   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3050 
3051 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3052           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3053 @*/
3054 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3055 {
3056   MatFactorInfo tinfo;
3057 
3058   PetscFunctionBegin;
3059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3060   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3061   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3062   if (info) PetscAssertPointer(info, 4);
3063   PetscValidType(mat, 1);
3064   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3065   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3066   MatCheckPreallocated(mat, 1);
3067   if (!info) {
3068     PetscCall(MatFactorInfoInitialize(&tinfo));
3069     info = &tinfo;
3070   }
3071 
3072   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3073   PetscUseTypeMethod(mat, lufactor, row, col, info);
3074   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3075   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3076   PetscFunctionReturn(PETSC_SUCCESS);
3077 }
3078 
3079 /*@C
3080   MatILUFactor - Performs in-place ILU factorization of matrix.
3081 
3082   Collective
3083 
3084   Input Parameters:
3085 + mat  - the matrix
3086 . row  - row permutation
3087 . col  - column permutation
3088 - info - structure containing
3089 .vb
3090       levels - number of levels of fill.
3091       expected fill - as ratio of original fill.
3092       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3093                 missing diagonal entries)
3094 .ve
3095 
3096   Level: developer
3097 
3098   Notes:
3099   Most users should employ the `KSP` interface for linear solvers
3100   instead of working directly with matrix algebra routines such as this.
3101   See, e.g., `KSPCreate()`.
3102 
3103   Probably really in-place only when level of fill is zero, otherwise allocates
3104   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3105   when not using `KSP`.
3106 
3107   Developer Note:
3108   The Fortran interface is not autogenerated as the
3109   interface definition cannot be generated correctly [due to MatFactorInfo]
3110 
3111 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3112 @*/
3113 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3114 {
3115   PetscFunctionBegin;
3116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3117   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3118   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3119   PetscAssertPointer(info, 4);
3120   PetscValidType(mat, 1);
3121   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3122   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3123   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3124   MatCheckPreallocated(mat, 1);
3125 
3126   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3127   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3128   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3129   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3130   PetscFunctionReturn(PETSC_SUCCESS);
3131 }
3132 
3133 /*@C
3134   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3135   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3136 
3137   Collective
3138 
3139   Input Parameters:
3140 + fact - the factor matrix obtained with `MatGetFactor()`
3141 . mat  - the matrix
3142 . row  - the row permutation
3143 . col  - the column permutation
3144 - info - options for factorization, includes
3145 .vb
3146           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3147           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3148 .ve
3149 
3150   Level: developer
3151 
3152   Notes:
3153   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3154 
3155   Most users should employ the simplified `KSP` interface for linear solvers
3156   instead of working directly with matrix algebra routines such as this.
3157   See, e.g., `KSPCreate()`.
3158 
3159   Developer Note:
3160   The Fortran interface is not autogenerated as the
3161   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3162 
3163 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3164 @*/
3165 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3166 {
3167   MatFactorInfo tinfo;
3168 
3169   PetscFunctionBegin;
3170   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3172   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3173   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3174   if (info) PetscAssertPointer(info, 5);
3175   PetscValidType(fact, 1);
3176   PetscValidType(mat, 2);
3177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3179   MatCheckPreallocated(mat, 2);
3180   if (!info) {
3181     PetscCall(MatFactorInfoInitialize(&tinfo));
3182     info = &tinfo;
3183   }
3184 
3185   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3186   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3187   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3188   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3189   PetscFunctionReturn(PETSC_SUCCESS);
3190 }
3191 
3192 /*@C
3193   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3194   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3195 
3196   Collective
3197 
3198   Input Parameters:
3199 + fact - the factor matrix obtained with `MatGetFactor()`
3200 . mat  - the matrix
3201 - info - options for factorization
3202 
3203   Level: developer
3204 
3205   Notes:
3206   See `MatLUFactor()` for in-place factorization.  See
3207   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3208 
3209   Most users should employ the `KSP` interface for linear solvers
3210   instead of working directly with matrix algebra routines such as this.
3211   See, e.g., `KSPCreate()`.
3212 
3213   Developer Note:
3214   The Fortran interface is not autogenerated as the
3215   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3216 
3217 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3218 @*/
3219 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3220 {
3221   MatFactorInfo tinfo;
3222 
3223   PetscFunctionBegin;
3224   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3226   PetscValidType(fact, 1);
3227   PetscValidType(mat, 2);
3228   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3229   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,
3230              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3231 
3232   MatCheckPreallocated(mat, 2);
3233   if (!info) {
3234     PetscCall(MatFactorInfoInitialize(&tinfo));
3235     info = &tinfo;
3236   }
3237 
3238   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3239   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3240   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3241   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3242   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3243   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3244   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3245   PetscFunctionReturn(PETSC_SUCCESS);
3246 }
3247 
3248 /*@C
3249   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3250   symmetric matrix.
3251 
3252   Collective
3253 
3254   Input Parameters:
3255 + mat  - the matrix
3256 . perm - row and column permutations
3257 - info - expected fill as ratio of original fill
3258 
3259   Level: developer
3260 
3261   Notes:
3262   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3263   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3264 
3265   Most users should employ the `KSP` interface for linear solvers
3266   instead of working directly with matrix algebra routines such as this.
3267   See, e.g., `KSPCreate()`.
3268 
3269   Developer Note:
3270   The Fortran interface is not autogenerated as the
3271   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3272 
3273 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3274           `MatGetOrdering()`
3275 @*/
3276 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3277 {
3278   MatFactorInfo tinfo;
3279 
3280   PetscFunctionBegin;
3281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3282   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3283   if (info) PetscAssertPointer(info, 3);
3284   PetscValidType(mat, 1);
3285   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3286   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3287   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3288   MatCheckPreallocated(mat, 1);
3289   if (!info) {
3290     PetscCall(MatFactorInfoInitialize(&tinfo));
3291     info = &tinfo;
3292   }
3293 
3294   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3295   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3296   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3297   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3298   PetscFunctionReturn(PETSC_SUCCESS);
3299 }
3300 
3301 /*@C
3302   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3303   of a symmetric matrix.
3304 
3305   Collective
3306 
3307   Input Parameters:
3308 + fact - the factor matrix obtained with `MatGetFactor()`
3309 . mat  - the matrix
3310 . perm - row and column permutations
3311 - info - options for factorization, includes
3312 .vb
3313           fill - expected fill as ratio of original fill.
3314           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3315                    Run with the option -info to determine an optimal value to use
3316 .ve
3317 
3318   Level: developer
3319 
3320   Notes:
3321   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3322   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3323 
3324   Most users should employ the `KSP` interface for linear solvers
3325   instead of working directly with matrix algebra routines such as this.
3326   See, e.g., `KSPCreate()`.
3327 
3328   Developer Note:
3329   The Fortran interface is not autogenerated as the
3330   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3331 
3332 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3333           `MatGetOrdering()`
3334 @*/
3335 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3336 {
3337   MatFactorInfo tinfo;
3338 
3339   PetscFunctionBegin;
3340   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3342   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3343   if (info) PetscAssertPointer(info, 4);
3344   PetscValidType(fact, 1);
3345   PetscValidType(mat, 2);
3346   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3347   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3348   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3349   MatCheckPreallocated(mat, 2);
3350   if (!info) {
3351     PetscCall(MatFactorInfoInitialize(&tinfo));
3352     info = &tinfo;
3353   }
3354 
3355   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3356   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3357   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3358   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3359   PetscFunctionReturn(PETSC_SUCCESS);
3360 }
3361 
3362 /*@C
3363   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3364   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3365   `MatCholeskyFactorSymbolic()`.
3366 
3367   Collective
3368 
3369   Input Parameters:
3370 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3371 . mat  - the initial matrix that is to be factored
3372 - info - options for factorization
3373 
3374   Level: developer
3375 
3376   Note:
3377   Most users should employ the `KSP` interface for linear solvers
3378   instead of working directly with matrix algebra routines such as this.
3379   See, e.g., `KSPCreate()`.
3380 
3381   Developer Note:
3382   The Fortran interface is not autogenerated as the
3383   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3384 
3385 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3386 @*/
3387 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3388 {
3389   MatFactorInfo tinfo;
3390 
3391   PetscFunctionBegin;
3392   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3394   PetscValidType(fact, 1);
3395   PetscValidType(mat, 2);
3396   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3397   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,
3398              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3399   MatCheckPreallocated(mat, 2);
3400   if (!info) {
3401     PetscCall(MatFactorInfoInitialize(&tinfo));
3402     info = &tinfo;
3403   }
3404 
3405   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3406   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3407   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3408   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3409   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3410   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3411   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3412   PetscFunctionReturn(PETSC_SUCCESS);
3413 }
3414 
3415 /*@
3416   MatQRFactor - Performs in-place QR factorization of matrix.
3417 
3418   Collective
3419 
3420   Input Parameters:
3421 + mat  - the matrix
3422 . col  - column permutation
3423 - info - options for factorization, includes
3424 .vb
3425           fill - expected fill as ratio of original fill.
3426           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3427                    Run with the option -info to determine an optimal value to use
3428 .ve
3429 
3430   Level: developer
3431 
3432   Notes:
3433   Most users should employ the `KSP` interface for linear solvers
3434   instead of working directly with matrix algebra routines such as this.
3435   See, e.g., `KSPCreate()`.
3436 
3437   This changes the state of the matrix to a factored matrix; it cannot be used
3438   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3439 
3440   Developer Note:
3441   The Fortran interface is not autogenerated as the
3442   interface definition cannot be generated correctly [due to MatFactorInfo]
3443 
3444 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3445           `MatSetUnfactored()`
3446 @*/
3447 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3448 {
3449   PetscFunctionBegin;
3450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3451   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3452   if (info) PetscAssertPointer(info, 3);
3453   PetscValidType(mat, 1);
3454   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3455   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3456   MatCheckPreallocated(mat, 1);
3457   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3458   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3459   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3460   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3461   PetscFunctionReturn(PETSC_SUCCESS);
3462 }
3463 
3464 /*@
3465   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3466   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3467 
3468   Collective
3469 
3470   Input Parameters:
3471 + fact - the factor matrix obtained with `MatGetFactor()`
3472 . mat  - the matrix
3473 . col  - column permutation
3474 - info - options for factorization, includes
3475 .vb
3476           fill - expected fill as ratio of original fill.
3477           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3478                    Run with the option -info to determine an optimal value to use
3479 .ve
3480 
3481   Level: developer
3482 
3483   Note:
3484   Most users should employ the `KSP` interface for linear solvers
3485   instead of working directly with matrix algebra routines such as this.
3486   See, e.g., `KSPCreate()`.
3487 
3488   Developer Note:
3489   The Fortran interface is not autogenerated as the
3490   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3491 
3492 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3493 @*/
3494 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3495 {
3496   MatFactorInfo tinfo;
3497 
3498   PetscFunctionBegin;
3499   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3501   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3502   if (info) PetscAssertPointer(info, 4);
3503   PetscValidType(fact, 1);
3504   PetscValidType(mat, 2);
3505   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3506   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3507   MatCheckPreallocated(mat, 2);
3508   if (!info) {
3509     PetscCall(MatFactorInfoInitialize(&tinfo));
3510     info = &tinfo;
3511   }
3512 
3513   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3514   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3515   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3516   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3517   PetscFunctionReturn(PETSC_SUCCESS);
3518 }
3519 
3520 /*@
3521   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3522   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3523 
3524   Collective
3525 
3526   Input Parameters:
3527 + fact - the factor matrix obtained with `MatGetFactor()`
3528 . mat  - the matrix
3529 - info - options for factorization
3530 
3531   Level: developer
3532 
3533   Notes:
3534   See `MatQRFactor()` for in-place factorization.
3535 
3536   Most users should employ the `KSP` interface for linear solvers
3537   instead of working directly with matrix algebra routines such as this.
3538   See, e.g., `KSPCreate()`.
3539 
3540   Developer Note:
3541   The Fortran interface is not autogenerated as the
3542   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3543 
3544 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3545 @*/
3546 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3547 {
3548   MatFactorInfo tinfo;
3549 
3550   PetscFunctionBegin;
3551   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3553   PetscValidType(fact, 1);
3554   PetscValidType(mat, 2);
3555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3556   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,
3557              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3558 
3559   MatCheckPreallocated(mat, 2);
3560   if (!info) {
3561     PetscCall(MatFactorInfoInitialize(&tinfo));
3562     info = &tinfo;
3563   }
3564 
3565   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3566   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3567   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3568   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3569   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3570   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3571   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3572   PetscFunctionReturn(PETSC_SUCCESS);
3573 }
3574 
3575 /*@
3576   MatSolve - Solves $A x = b$, given a factored matrix.
3577 
3578   Neighbor-wise Collective
3579 
3580   Input Parameters:
3581 + mat - the factored matrix
3582 - b   - the right-hand-side vector
3583 
3584   Output Parameter:
3585 . x - the result vector
3586 
3587   Level: developer
3588 
3589   Notes:
3590   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3591   call `MatSolve`(A,x,x).
3592 
3593   Most users should employ the `KSP` interface for linear solvers
3594   instead of working directly with matrix algebra routines such as this.
3595   See, e.g., `KSPCreate()`.
3596 
3597 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3598 @*/
3599 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3600 {
3601   PetscFunctionBegin;
3602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3603   PetscValidType(mat, 1);
3604   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3605   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3606   PetscCheckSameComm(mat, 1, b, 2);
3607   PetscCheckSameComm(mat, 1, x, 3);
3608   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3609   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);
3610   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);
3611   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);
3612   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3613   MatCheckPreallocated(mat, 1);
3614 
3615   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3616   if (mat->factorerrortype) {
3617     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3618     PetscCall(VecSetInf(x));
3619   } else PetscUseTypeMethod(mat, solve, b, x);
3620   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3621   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3622   PetscFunctionReturn(PETSC_SUCCESS);
3623 }
3624 
3625 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3626 {
3627   Vec      b, x;
3628   PetscInt N, i;
3629   PetscErrorCode (*f)(Mat, Vec, Vec);
3630   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3631 
3632   PetscFunctionBegin;
3633   if (A->factorerrortype) {
3634     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3635     PetscCall(MatSetInf(X));
3636     PetscFunctionReturn(PETSC_SUCCESS);
3637   }
3638   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3639   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3640   PetscCall(MatBoundToCPU(A, &Abound));
3641   if (!Abound) {
3642     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3643     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3644   }
3645 #if PetscDefined(HAVE_CUDA)
3646   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3647   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3648 #elif PetscDefined(HAVE_HIP)
3649   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3650   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3651 #endif
3652   PetscCall(MatGetSize(B, NULL, &N));
3653   for (i = 0; i < N; i++) {
3654     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3655     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3656     PetscCall((*f)(A, b, x));
3657     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3658     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3659   }
3660   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3661   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3662   PetscFunctionReturn(PETSC_SUCCESS);
3663 }
3664 
3665 /*@
3666   MatMatSolve - Solves $A X = B$, given a factored matrix.
3667 
3668   Neighbor-wise Collective
3669 
3670   Input Parameters:
3671 + A - the factored matrix
3672 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3673 
3674   Output Parameter:
3675 . X - the result matrix (dense matrix)
3676 
3677   Level: developer
3678 
3679   Note:
3680   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3681   otherwise, `B` and `X` cannot be the same.
3682 
3683 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3684 @*/
3685 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3686 {
3687   PetscFunctionBegin;
3688   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3689   PetscValidType(A, 1);
3690   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3691   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3692   PetscCheckSameComm(A, 1, B, 2);
3693   PetscCheckSameComm(A, 1, X, 3);
3694   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);
3695   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);
3696   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");
3697   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3698   MatCheckPreallocated(A, 1);
3699 
3700   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3701   if (!A->ops->matsolve) {
3702     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3703     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3704   } else PetscUseTypeMethod(A, matsolve, B, X);
3705   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3706   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3707   PetscFunctionReturn(PETSC_SUCCESS);
3708 }
3709 
3710 /*@
3711   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3712 
3713   Neighbor-wise Collective
3714 
3715   Input Parameters:
3716 + A - the factored matrix
3717 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3718 
3719   Output Parameter:
3720 . X - the result matrix (dense matrix)
3721 
3722   Level: developer
3723 
3724   Note:
3725   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3726   call `MatMatSolveTranspose`(A,X,X).
3727 
3728 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3729 @*/
3730 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3731 {
3732   PetscFunctionBegin;
3733   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3734   PetscValidType(A, 1);
3735   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3736   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3737   PetscCheckSameComm(A, 1, B, 2);
3738   PetscCheckSameComm(A, 1, X, 3);
3739   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3740   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);
3741   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);
3742   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);
3743   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");
3744   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3745   MatCheckPreallocated(A, 1);
3746 
3747   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3748   if (!A->ops->matsolvetranspose) {
3749     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3750     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3751   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3752   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3753   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3754   PetscFunctionReturn(PETSC_SUCCESS);
3755 }
3756 
3757 /*@
3758   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3759 
3760   Neighbor-wise Collective
3761 
3762   Input Parameters:
3763 + A  - the factored matrix
3764 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3765 
3766   Output Parameter:
3767 . X - the result matrix (dense matrix)
3768 
3769   Level: developer
3770 
3771   Note:
3772   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
3773   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3774 
3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3776 @*/
3777 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3778 {
3779   PetscFunctionBegin;
3780   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3781   PetscValidType(A, 1);
3782   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3783   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3784   PetscCheckSameComm(A, 1, Bt, 2);
3785   PetscCheckSameComm(A, 1, X, 3);
3786 
3787   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3788   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);
3789   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);
3790   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");
3791   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3792   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3793   MatCheckPreallocated(A, 1);
3794 
3795   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3796   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3797   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3798   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3799   PetscFunctionReturn(PETSC_SUCCESS);
3800 }
3801 
3802 /*@
3803   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3804   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3805 
3806   Neighbor-wise Collective
3807 
3808   Input Parameters:
3809 + mat - the factored matrix
3810 - b   - the right-hand-side vector
3811 
3812   Output Parameter:
3813 . x - the result vector
3814 
3815   Level: developer
3816 
3817   Notes:
3818   `MatSolve()` should be used for most applications, as it performs
3819   a forward solve followed by a backward solve.
3820 
3821   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3822   call `MatForwardSolve`(A,x,x).
3823 
3824   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3825   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3826   `MatForwardSolve()` solves $U^T*D y = b$, and
3827   `MatBackwardSolve()` solves $U x = y$.
3828   Thus they do not provide a symmetric preconditioner.
3829 
3830 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3831 @*/
3832 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3833 {
3834   PetscFunctionBegin;
3835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3836   PetscValidType(mat, 1);
3837   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3838   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3839   PetscCheckSameComm(mat, 1, b, 2);
3840   PetscCheckSameComm(mat, 1, x, 3);
3841   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3842   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);
3843   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);
3844   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);
3845   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3846   MatCheckPreallocated(mat, 1);
3847 
3848   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3849   PetscUseTypeMethod(mat, forwardsolve, b, x);
3850   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3851   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3852   PetscFunctionReturn(PETSC_SUCCESS);
3853 }
3854 
3855 /*@
3856   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3857   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3858 
3859   Neighbor-wise Collective
3860 
3861   Input Parameters:
3862 + mat - the factored matrix
3863 - b   - the right-hand-side vector
3864 
3865   Output Parameter:
3866 . x - the result vector
3867 
3868   Level: developer
3869 
3870   Notes:
3871   `MatSolve()` should be used for most applications, as it performs
3872   a forward solve followed by a backward solve.
3873 
3874   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3875   call `MatBackwardSolve`(A,x,x).
3876 
3877   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3878   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3879   `MatForwardSolve()` solves $U^T*D y = b$, and
3880   `MatBackwardSolve()` solves $U x = y$.
3881   Thus they do not provide a symmetric preconditioner.
3882 
3883 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3884 @*/
3885 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3886 {
3887   PetscFunctionBegin;
3888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3889   PetscValidType(mat, 1);
3890   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3891   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3892   PetscCheckSameComm(mat, 1, b, 2);
3893   PetscCheckSameComm(mat, 1, x, 3);
3894   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3895   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);
3896   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);
3897   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);
3898   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3899   MatCheckPreallocated(mat, 1);
3900 
3901   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3902   PetscUseTypeMethod(mat, backwardsolve, b, x);
3903   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3904   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3905   PetscFunctionReturn(PETSC_SUCCESS);
3906 }
3907 
3908 /*@
3909   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3910 
3911   Neighbor-wise Collective
3912 
3913   Input Parameters:
3914 + mat - the factored matrix
3915 . b   - the right-hand-side vector
3916 - y   - the vector to be added to
3917 
3918   Output Parameter:
3919 . x - the result vector
3920 
3921   Level: developer
3922 
3923   Note:
3924   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3925   call `MatSolveAdd`(A,x,y,x).
3926 
3927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3928 @*/
3929 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3930 {
3931   PetscScalar one = 1.0;
3932   Vec         tmp;
3933 
3934   PetscFunctionBegin;
3935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3936   PetscValidType(mat, 1);
3937   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3938   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3939   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3940   PetscCheckSameComm(mat, 1, b, 2);
3941   PetscCheckSameComm(mat, 1, y, 3);
3942   PetscCheckSameComm(mat, 1, x, 4);
3943   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3944   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);
3945   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);
3946   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);
3947   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);
3948   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);
3949   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3950   MatCheckPreallocated(mat, 1);
3951 
3952   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3953   if (mat->factorerrortype) {
3954     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3955     PetscCall(VecSetInf(x));
3956   } else if (mat->ops->solveadd) {
3957     PetscUseTypeMethod(mat, solveadd, b, y, x);
3958   } else {
3959     /* do the solve then the add manually */
3960     if (x != y) {
3961       PetscCall(MatSolve(mat, b, x));
3962       PetscCall(VecAXPY(x, one, y));
3963     } else {
3964       PetscCall(VecDuplicate(x, &tmp));
3965       PetscCall(VecCopy(x, tmp));
3966       PetscCall(MatSolve(mat, b, x));
3967       PetscCall(VecAXPY(x, one, tmp));
3968       PetscCall(VecDestroy(&tmp));
3969     }
3970   }
3971   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3972   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3973   PetscFunctionReturn(PETSC_SUCCESS);
3974 }
3975 
3976 /*@
3977   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3978 
3979   Neighbor-wise Collective
3980 
3981   Input Parameters:
3982 + mat - the factored matrix
3983 - b   - the right-hand-side vector
3984 
3985   Output Parameter:
3986 . x - the result vector
3987 
3988   Level: developer
3989 
3990   Notes:
3991   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3992   call `MatSolveTranspose`(A,x,x).
3993 
3994   Most users should employ the `KSP` interface for linear solvers
3995   instead of working directly with matrix algebra routines such as this.
3996   See, e.g., `KSPCreate()`.
3997 
3998 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3999 @*/
4000 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4001 {
4002   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4003 
4004   PetscFunctionBegin;
4005   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4006   PetscValidType(mat, 1);
4007   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4008   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4009   PetscCheckSameComm(mat, 1, b, 2);
4010   PetscCheckSameComm(mat, 1, x, 3);
4011   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4012   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);
4013   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);
4014   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4015   MatCheckPreallocated(mat, 1);
4016   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4017   if (mat->factorerrortype) {
4018     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4019     PetscCall(VecSetInf(x));
4020   } else {
4021     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4022     PetscCall((*f)(mat, b, x));
4023   }
4024   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4025   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4026   PetscFunctionReturn(PETSC_SUCCESS);
4027 }
4028 
4029 /*@
4030   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4031   factored matrix.
4032 
4033   Neighbor-wise Collective
4034 
4035   Input Parameters:
4036 + mat - the factored matrix
4037 . b   - the right-hand-side vector
4038 - y   - the vector to be added to
4039 
4040   Output Parameter:
4041 . x - the result vector
4042 
4043   Level: developer
4044 
4045   Note:
4046   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4047   call `MatSolveTransposeAdd`(A,x,y,x).
4048 
4049 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4050 @*/
4051 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4052 {
4053   PetscScalar one = 1.0;
4054   Vec         tmp;
4055   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4056 
4057   PetscFunctionBegin;
4058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4059   PetscValidType(mat, 1);
4060   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4061   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4062   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4063   PetscCheckSameComm(mat, 1, b, 2);
4064   PetscCheckSameComm(mat, 1, y, 3);
4065   PetscCheckSameComm(mat, 1, x, 4);
4066   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4067   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);
4068   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);
4069   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);
4070   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);
4071   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4072   MatCheckPreallocated(mat, 1);
4073 
4074   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4075   if (mat->factorerrortype) {
4076     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4077     PetscCall(VecSetInf(x));
4078   } else if (f) {
4079     PetscCall((*f)(mat, b, y, x));
4080   } else {
4081     /* do the solve then the add manually */
4082     if (x != y) {
4083       PetscCall(MatSolveTranspose(mat, b, x));
4084       PetscCall(VecAXPY(x, one, y));
4085     } else {
4086       PetscCall(VecDuplicate(x, &tmp));
4087       PetscCall(VecCopy(x, tmp));
4088       PetscCall(MatSolveTranspose(mat, b, x));
4089       PetscCall(VecAXPY(x, one, tmp));
4090       PetscCall(VecDestroy(&tmp));
4091     }
4092   }
4093   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4094   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4095   PetscFunctionReturn(PETSC_SUCCESS);
4096 }
4097 
4098 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4099 /*@
4100   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4101 
4102   Neighbor-wise Collective
4103 
4104   Input Parameters:
4105 + mat   - the matrix
4106 . b     - the right hand side
4107 . omega - the relaxation factor
4108 . flag  - flag indicating the type of SOR (see below)
4109 . shift - diagonal shift
4110 . its   - the number of iterations
4111 - lits  - the number of local iterations
4112 
4113   Output Parameter:
4114 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4115 
4116   SOR Flags:
4117 +     `SOR_FORWARD_SWEEP` - forward SOR
4118 .     `SOR_BACKWARD_SWEEP` - backward SOR
4119 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4120 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4121 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4122 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4123 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4124 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4125   upper/lower triangular part of matrix to
4126   vector (with omega)
4127 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4128 
4129   Level: developer
4130 
4131   Notes:
4132   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4133   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4134   on each processor.
4135 
4136   Application programmers will not generally use `MatSOR()` directly,
4137   but instead will employ the `KSP`/`PC` interface.
4138 
4139   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4140 
4141   Most users should employ the `KSP` interface for linear solvers
4142   instead of working directly with matrix algebra routines such as this.
4143   See, e.g., `KSPCreate()`.
4144 
4145   Vectors `x` and `b` CANNOT be the same
4146 
4147   The flags are implemented as bitwise inclusive or operations.
4148   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4149   to specify a zero initial guess for SSOR.
4150 
4151   Developer Note:
4152   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4153 
4154 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4155 @*/
4156 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4157 {
4158   PetscFunctionBegin;
4159   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4160   PetscValidType(mat, 1);
4161   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4162   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4163   PetscCheckSameComm(mat, 1, b, 2);
4164   PetscCheckSameComm(mat, 1, x, 8);
4165   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4166   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4167   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);
4168   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);
4169   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);
4170   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4171   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4172   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4173 
4174   MatCheckPreallocated(mat, 1);
4175   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4176   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4177   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4178   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4179   PetscFunctionReturn(PETSC_SUCCESS);
4180 }
4181 
4182 /*
4183       Default matrix copy routine.
4184 */
4185 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4186 {
4187   PetscInt           i, rstart = 0, rend = 0, nz;
4188   const PetscInt    *cwork;
4189   const PetscScalar *vwork;
4190 
4191   PetscFunctionBegin;
4192   if (B->assembled) PetscCall(MatZeroEntries(B));
4193   if (str == SAME_NONZERO_PATTERN) {
4194     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4195     for (i = rstart; i < rend; i++) {
4196       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4197       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4198       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4199     }
4200   } else {
4201     PetscCall(MatAYPX(B, 0.0, A, str));
4202   }
4203   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4204   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4205   PetscFunctionReturn(PETSC_SUCCESS);
4206 }
4207 
4208 /*@
4209   MatCopy - Copies a matrix to another matrix.
4210 
4211   Collective
4212 
4213   Input Parameters:
4214 + A   - the matrix
4215 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4216 
4217   Output Parameter:
4218 . B - where the copy is put
4219 
4220   Level: intermediate
4221 
4222   Notes:
4223   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4224 
4225   `MatCopy()` copies the matrix entries of a matrix to another existing
4226   matrix (after first zeroing the second matrix).  A related routine is
4227   `MatConvert()`, which first creates a new matrix and then copies the data.
4228 
4229 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4230 @*/
4231 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4232 {
4233   PetscInt i;
4234 
4235   PetscFunctionBegin;
4236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4237   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4238   PetscValidType(A, 1);
4239   PetscValidType(B, 2);
4240   PetscCheckSameComm(A, 1, B, 2);
4241   MatCheckPreallocated(B, 2);
4242   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4243   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4244   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,
4245              A->cmap->N, B->cmap->N);
4246   MatCheckPreallocated(A, 1);
4247   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4248 
4249   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4250   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4251   else PetscCall(MatCopy_Basic(A, B, str));
4252 
4253   B->stencil.dim = A->stencil.dim;
4254   B->stencil.noc = A->stencil.noc;
4255   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4256     B->stencil.dims[i]   = A->stencil.dims[i];
4257     B->stencil.starts[i] = A->stencil.starts[i];
4258   }
4259 
4260   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4261   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4262   PetscFunctionReturn(PETSC_SUCCESS);
4263 }
4264 
4265 /*@C
4266   MatConvert - Converts a matrix to another matrix, either of the same
4267   or different type.
4268 
4269   Collective
4270 
4271   Input Parameters:
4272 + mat     - the matrix
4273 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4274    same type as the original matrix.
4275 - reuse   - denotes if the destination matrix is to be created or reused.
4276    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
4277    `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).
4278 
4279   Output Parameter:
4280 . M - pointer to place new matrix
4281 
4282   Level: intermediate
4283 
4284   Notes:
4285   `MatConvert()` first creates a new matrix and then copies the data from
4286   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4287   entries of one matrix to another already existing matrix context.
4288 
4289   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4290   the MPI communicator of the generated matrix is always the same as the communicator
4291   of the input matrix.
4292 
4293 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4294 @*/
4295 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4296 {
4297   PetscBool  sametype, issame, flg;
4298   PetscBool3 issymmetric, ishermitian;
4299   char       convname[256], mtype[256];
4300   Mat        B;
4301 
4302   PetscFunctionBegin;
4303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4304   PetscValidType(mat, 1);
4305   PetscAssertPointer(M, 4);
4306   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4307   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4308   MatCheckPreallocated(mat, 1);
4309 
4310   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4311   if (flg) newtype = mtype;
4312 
4313   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4314   PetscCall(PetscStrcmp(newtype, "same", &issame));
4315   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4316   if (reuse == MAT_REUSE_MATRIX) {
4317     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4318     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4319   }
4320 
4321   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4322     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4323     PetscFunctionReturn(PETSC_SUCCESS);
4324   }
4325 
4326   /* Cache Mat options because some converters use MatHeaderReplace  */
4327   issymmetric = mat->symmetric;
4328   ishermitian = mat->hermitian;
4329 
4330   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4331     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4332     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4333   } else {
4334     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4335     const char *prefix[3]                                 = {"seq", "mpi", ""};
4336     PetscInt    i;
4337     /*
4338        Order of precedence:
4339        0) See if newtype is a superclass of the current matrix.
4340        1) See if a specialized converter is known to the current matrix.
4341        2) See if a specialized converter is known to the desired matrix class.
4342        3) See if a good general converter is registered for the desired class
4343           (as of 6/27/03 only MATMPIADJ falls into this category).
4344        4) See if a good general converter is known for the current matrix.
4345        5) Use a really basic converter.
4346     */
4347 
4348     /* 0) See if newtype is a superclass of the current matrix.
4349           i.e mat is mpiaij and newtype is aij */
4350     for (i = 0; i < 2; i++) {
4351       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4353       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4354       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4355       if (flg) {
4356         if (reuse == MAT_INPLACE_MATRIX) {
4357           PetscCall(PetscInfo(mat, "Early return\n"));
4358           PetscFunctionReturn(PETSC_SUCCESS);
4359         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4360           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4361           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4362           PetscFunctionReturn(PETSC_SUCCESS);
4363         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4364           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4365           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         }
4368       }
4369     }
4370     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4371     for (i = 0; i < 3; i++) {
4372       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4378       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4379       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4380       if (conv) goto foundconv;
4381     }
4382 
4383     /* 2)  See if a specialized converter is known to the desired matrix class. */
4384     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4385     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4386     PetscCall(MatSetType(B, newtype));
4387     for (i = 0; i < 3; i++) {
4388       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4390       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4394       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4395       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4396       if (conv) {
4397         PetscCall(MatDestroy(&B));
4398         goto foundconv;
4399       }
4400     }
4401 
4402     /* 3) See if a good general converter is registered for the desired class */
4403     conv = B->ops->convertfrom;
4404     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4405     PetscCall(MatDestroy(&B));
4406     if (conv) goto foundconv;
4407 
4408     /* 4) See if a good general converter is known for the current matrix */
4409     if (mat->ops->convert) conv = mat->ops->convert;
4410     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4411     if (conv) goto foundconv;
4412 
4413     /* 5) Use a really basic converter. */
4414     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4415     conv = MatConvert_Basic;
4416 
4417   foundconv:
4418     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4419     PetscCall((*conv)(mat, newtype, reuse, M));
4420     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4421       /* the block sizes must be same if the mappings are copied over */
4422       (*M)->rmap->bs = mat->rmap->bs;
4423       (*M)->cmap->bs = mat->cmap->bs;
4424       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4425       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4426       (*M)->rmap->mapping = mat->rmap->mapping;
4427       (*M)->cmap->mapping = mat->cmap->mapping;
4428     }
4429     (*M)->stencil.dim = mat->stencil.dim;
4430     (*M)->stencil.noc = mat->stencil.noc;
4431     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4432       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4433       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4434     }
4435     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4436   }
4437   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4438 
4439   /* Copy Mat options */
4440   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4441   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4442   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4443   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4444   PetscFunctionReturn(PETSC_SUCCESS);
4445 }
4446 
4447 /*@C
4448   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4449 
4450   Not Collective
4451 
4452   Input Parameter:
4453 . mat - the matrix, must be a factored matrix
4454 
4455   Output Parameter:
4456 . type - the string name of the package (do not free this string)
4457 
4458   Level: intermediate
4459 
4460   Fortran Note:
4461   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4462 
4463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4464 @*/
4465 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4466 {
4467   PetscErrorCode (*conv)(Mat, MatSolverType *);
4468 
4469   PetscFunctionBegin;
4470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4471   PetscValidType(mat, 1);
4472   PetscAssertPointer(type, 2);
4473   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4474   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4475   if (conv) PetscCall((*conv)(mat, type));
4476   else *type = MATSOLVERPETSC;
4477   PetscFunctionReturn(PETSC_SUCCESS);
4478 }
4479 
4480 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4481 struct _MatSolverTypeForSpecifcType {
4482   MatType mtype;
4483   /* no entry for MAT_FACTOR_NONE */
4484   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4485   MatSolverTypeForSpecifcType next;
4486 };
4487 
4488 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4489 struct _MatSolverTypeHolder {
4490   char                       *name;
4491   MatSolverTypeForSpecifcType handlers;
4492   MatSolverTypeHolder         next;
4493 };
4494 
4495 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4496 
4497 /*@C
4498   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4499 
4500   Input Parameters:
4501 + package      - name of the package, for example petsc or superlu
4502 . mtype        - the matrix type that works with this package
4503 . ftype        - the type of factorization supported by the package
4504 - createfactor - routine that will create the factored matrix ready to be used
4505 
4506   Level: developer
4507 
4508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4509   `MatGetFactor()`
4510 @*/
4511 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4512 {
4513   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4514   PetscBool                   flg;
4515   MatSolverTypeForSpecifcType inext, iprev = NULL;
4516 
4517   PetscFunctionBegin;
4518   PetscCall(MatInitializePackage());
4519   if (!next) {
4520     PetscCall(PetscNew(&MatSolverTypeHolders));
4521     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4522     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4523     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4524     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4525     PetscFunctionReturn(PETSC_SUCCESS);
4526   }
4527   while (next) {
4528     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4529     if (flg) {
4530       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4531       inext = next->handlers;
4532       while (inext) {
4533         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4534         if (flg) {
4535           inext->createfactor[(int)ftype - 1] = createfactor;
4536           PetscFunctionReturn(PETSC_SUCCESS);
4537         }
4538         iprev = inext;
4539         inext = inext->next;
4540       }
4541       PetscCall(PetscNew(&iprev->next));
4542       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4543       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4544       PetscFunctionReturn(PETSC_SUCCESS);
4545     }
4546     prev = next;
4547     next = next->next;
4548   }
4549   PetscCall(PetscNew(&prev->next));
4550   PetscCall(PetscStrallocpy(package, &prev->next->name));
4551   PetscCall(PetscNew(&prev->next->handlers));
4552   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4553   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4554   PetscFunctionReturn(PETSC_SUCCESS);
4555 }
4556 
4557 /*@C
4558   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4559 
4560   Input Parameters:
4561 + 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
4562 . ftype - the type of factorization supported by the type
4563 - mtype - the matrix type that works with this type
4564 
4565   Output Parameters:
4566 + foundtype    - `PETSC_TRUE` if the type was registered
4567 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4568 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4569 
4570   Calling sequence of `createfactor`:
4571 + A     - the matrix providing the factor matrix
4572 . mtype - the `MatType` of the factor requested
4573 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4574 
4575   Level: developer
4576 
4577   Note:
4578   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4579   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4580   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4581 
4582 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4583           `MatInitializePackage()`
4584 @*/
4585 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4586 {
4587   MatSolverTypeHolder         next = MatSolverTypeHolders;
4588   PetscBool                   flg;
4589   MatSolverTypeForSpecifcType inext;
4590 
4591   PetscFunctionBegin;
4592   if (foundtype) *foundtype = PETSC_FALSE;
4593   if (foundmtype) *foundmtype = PETSC_FALSE;
4594   if (createfactor) *createfactor = NULL;
4595 
4596   if (type) {
4597     while (next) {
4598       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4599       if (flg) {
4600         if (foundtype) *foundtype = PETSC_TRUE;
4601         inext = next->handlers;
4602         while (inext) {
4603           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4604           if (flg) {
4605             if (foundmtype) *foundmtype = PETSC_TRUE;
4606             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4607             PetscFunctionReturn(PETSC_SUCCESS);
4608           }
4609           inext = inext->next;
4610         }
4611       }
4612       next = next->next;
4613     }
4614   } else {
4615     while (next) {
4616       inext = next->handlers;
4617       while (inext) {
4618         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4619         if (flg && inext->createfactor[(int)ftype - 1]) {
4620           if (foundtype) *foundtype = PETSC_TRUE;
4621           if (foundmtype) *foundmtype = PETSC_TRUE;
4622           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4623           PetscFunctionReturn(PETSC_SUCCESS);
4624         }
4625         inext = inext->next;
4626       }
4627       next = next->next;
4628     }
4629     /* try with base classes inext->mtype */
4630     next = MatSolverTypeHolders;
4631     while (next) {
4632       inext = next->handlers;
4633       while (inext) {
4634         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4635         if (flg && inext->createfactor[(int)ftype - 1]) {
4636           if (foundtype) *foundtype = PETSC_TRUE;
4637           if (foundmtype) *foundmtype = PETSC_TRUE;
4638           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4639           PetscFunctionReturn(PETSC_SUCCESS);
4640         }
4641         inext = inext->next;
4642       }
4643       next = next->next;
4644     }
4645   }
4646   PetscFunctionReturn(PETSC_SUCCESS);
4647 }
4648 
4649 PetscErrorCode MatSolverTypeDestroy(void)
4650 {
4651   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4652   MatSolverTypeForSpecifcType inext, iprev;
4653 
4654   PetscFunctionBegin;
4655   while (next) {
4656     PetscCall(PetscFree(next->name));
4657     inext = next->handlers;
4658     while (inext) {
4659       PetscCall(PetscFree(inext->mtype));
4660       iprev = inext;
4661       inext = inext->next;
4662       PetscCall(PetscFree(iprev));
4663     }
4664     prev = next;
4665     next = next->next;
4666     PetscCall(PetscFree(prev));
4667   }
4668   MatSolverTypeHolders = NULL;
4669   PetscFunctionReturn(PETSC_SUCCESS);
4670 }
4671 
4672 /*@C
4673   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4674 
4675   Logically Collective
4676 
4677   Input Parameter:
4678 . mat - the matrix
4679 
4680   Output Parameter:
4681 . flg - `PETSC_TRUE` if uses the ordering
4682 
4683   Level: developer
4684 
4685   Note:
4686   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4687   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4688 
4689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4690 @*/
4691 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4692 {
4693   PetscFunctionBegin;
4694   *flg = mat->canuseordering;
4695   PetscFunctionReturn(PETSC_SUCCESS);
4696 }
4697 
4698 /*@C
4699   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4700 
4701   Logically Collective
4702 
4703   Input Parameters:
4704 + mat   - the matrix obtained with `MatGetFactor()`
4705 - ftype - the factorization type to be used
4706 
4707   Output Parameter:
4708 . otype - the preferred ordering type
4709 
4710   Level: developer
4711 
4712 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4713 @*/
4714 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4715 {
4716   PetscFunctionBegin;
4717   *otype = mat->preferredordering[ftype];
4718   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4719   PetscFunctionReturn(PETSC_SUCCESS);
4720 }
4721 
4722 /*@C
4723   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4724 
4725   Collective
4726 
4727   Input Parameters:
4728 + mat   - the matrix
4729 . 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
4730           the other criteria is returned
4731 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4732 
4733   Output Parameter:
4734 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4735 
4736   Options Database Keys:
4737 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4738 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4739                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4740 
4741   Level: intermediate
4742 
4743   Notes:
4744   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4745   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4746 
4747   Users usually access the factorization solvers via `KSP`
4748 
4749   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4750   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
4751 
4752   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4753   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4754   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4755 
4756   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4757   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4758   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4759 
4760   Developer Note:
4761   This should actually be called `MatCreateFactor()` since it creates a new factor object
4762 
4763 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4764           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4765           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4766 @*/
4767 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4768 {
4769   PetscBool foundtype, foundmtype;
4770   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4771 
4772   PetscFunctionBegin;
4773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4774   PetscValidType(mat, 1);
4775 
4776   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4777   MatCheckPreallocated(mat, 1);
4778 
4779   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4780   if (!foundtype) {
4781     if (type) {
4782       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],
4783               ((PetscObject)mat)->type_name, type);
4784     } else {
4785       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);
4786     }
4787   }
4788   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4789   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);
4790 
4791   PetscCall((*conv)(mat, ftype, f));
4792   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4793   PetscFunctionReturn(PETSC_SUCCESS);
4794 }
4795 
4796 /*@C
4797   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4798 
4799   Not Collective
4800 
4801   Input Parameters:
4802 + mat   - the matrix
4803 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4804 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4805 
4806   Output Parameter:
4807 . flg - PETSC_TRUE if the factorization is available
4808 
4809   Level: intermediate
4810 
4811   Notes:
4812   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4813   such as pastix, superlu, mumps etc.
4814 
4815   PETSc must have been ./configure to use the external solver, using the option --download-package
4816 
4817   Developer Note:
4818   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4819 
4820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4821           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4822 @*/
4823 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4824 {
4825   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4826 
4827   PetscFunctionBegin;
4828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4829   PetscValidType(mat, 1);
4830   PetscAssertPointer(flg, 4);
4831 
4832   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4833   MatCheckPreallocated(mat, 1);
4834 
4835   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4836   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4837   PetscFunctionReturn(PETSC_SUCCESS);
4838 }
4839 
4840 /*@
4841   MatDuplicate - Duplicates a matrix including the non-zero structure.
4842 
4843   Collective
4844 
4845   Input Parameters:
4846 + mat - the matrix
4847 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4848         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4849 
4850   Output Parameter:
4851 . M - pointer to place new matrix
4852 
4853   Level: intermediate
4854 
4855   Notes:
4856   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4857 
4858   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4859 
4860   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.
4861 
4862   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4863   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4864   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4865 
4866 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4867 @*/
4868 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4869 {
4870   Mat         B;
4871   VecType     vtype;
4872   PetscInt    i;
4873   PetscObject dm, container_h, container_d;
4874   void (*viewf)(void);
4875 
4876   PetscFunctionBegin;
4877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4878   PetscValidType(mat, 1);
4879   PetscAssertPointer(M, 3);
4880   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4881   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4882   MatCheckPreallocated(mat, 1);
4883 
4884   *M = NULL;
4885   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4886   PetscUseTypeMethod(mat, duplicate, op, M);
4887   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4888   B = *M;
4889 
4890   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4891   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4892   PetscCall(MatGetVecType(mat, &vtype));
4893   PetscCall(MatSetVecType(B, vtype));
4894 
4895   B->stencil.dim = mat->stencil.dim;
4896   B->stencil.noc = mat->stencil.noc;
4897   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4898     B->stencil.dims[i]   = mat->stencil.dims[i];
4899     B->stencil.starts[i] = mat->stencil.starts[i];
4900   }
4901 
4902   B->nooffproczerorows = mat->nooffproczerorows;
4903   B->nooffprocentries  = mat->nooffprocentries;
4904 
4905   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4906   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4907   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4908   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4909   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4910   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4911   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4912   PetscFunctionReturn(PETSC_SUCCESS);
4913 }
4914 
4915 /*@
4916   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4917 
4918   Logically Collective
4919 
4920   Input Parameter:
4921 . mat - the matrix
4922 
4923   Output Parameter:
4924 . v - the diagonal of the matrix
4925 
4926   Level: intermediate
4927 
4928   Note:
4929   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4930   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4931   is larger than `ndiag`, the values of the remaining entries are unspecified.
4932 
4933   Currently only correct in parallel for square matrices.
4934 
4935 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4936 @*/
4937 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4938 {
4939   PetscFunctionBegin;
4940   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4941   PetscValidType(mat, 1);
4942   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4943   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4944   MatCheckPreallocated(mat, 1);
4945   if (PetscDefined(USE_DEBUG)) {
4946     PetscInt nv, row, col, ndiag;
4947 
4948     PetscCall(VecGetLocalSize(v, &nv));
4949     PetscCall(MatGetLocalSize(mat, &row, &col));
4950     ndiag = PetscMin(row, col);
4951     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);
4952   }
4953 
4954   PetscUseTypeMethod(mat, getdiagonal, v);
4955   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4956   PetscFunctionReturn(PETSC_SUCCESS);
4957 }
4958 
4959 /*@C
4960   MatGetRowMin - Gets the minimum value (of the real part) of each
4961   row of the matrix
4962 
4963   Logically Collective
4964 
4965   Input Parameter:
4966 . mat - the matrix
4967 
4968   Output Parameters:
4969 + v   - the vector for storing the maximums
4970 - idx - the indices of the column found for each row (optional)
4971 
4972   Level: intermediate
4973 
4974   Note:
4975   The result of this call are the same as if one converted the matrix to dense format
4976   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4977 
4978   This code is only implemented for a couple of matrix formats.
4979 
4980 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4981           `MatGetRowMax()`
4982 @*/
4983 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4984 {
4985   PetscFunctionBegin;
4986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4987   PetscValidType(mat, 1);
4988   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4989   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4990 
4991   if (!mat->cmap->N) {
4992     PetscCall(VecSet(v, PETSC_MAX_REAL));
4993     if (idx) {
4994       PetscInt i, m = mat->rmap->n;
4995       for (i = 0; i < m; i++) idx[i] = -1;
4996     }
4997   } else {
4998     MatCheckPreallocated(mat, 1);
4999   }
5000   PetscUseTypeMethod(mat, getrowmin, v, idx);
5001   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5002   PetscFunctionReturn(PETSC_SUCCESS);
5003 }
5004 
5005 /*@C
5006   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5007   row of the matrix
5008 
5009   Logically Collective
5010 
5011   Input Parameter:
5012 . mat - the matrix
5013 
5014   Output Parameters:
5015 + v   - the vector for storing the minimums
5016 - idx - the indices of the column found for each row (or `NULL` if not needed)
5017 
5018   Level: intermediate
5019 
5020   Notes:
5021   if a row is completely empty or has only 0.0 values then the `idx` value for that
5022   row is 0 (the first column).
5023 
5024   This code is only implemented for a couple of matrix formats.
5025 
5026 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5027 @*/
5028 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5029 {
5030   PetscFunctionBegin;
5031   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5032   PetscValidType(mat, 1);
5033   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5034   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5035   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5036 
5037   if (!mat->cmap->N) {
5038     PetscCall(VecSet(v, 0.0));
5039     if (idx) {
5040       PetscInt i, m = mat->rmap->n;
5041       for (i = 0; i < m; i++) idx[i] = -1;
5042     }
5043   } else {
5044     MatCheckPreallocated(mat, 1);
5045     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5046     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5047   }
5048   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5049   PetscFunctionReturn(PETSC_SUCCESS);
5050 }
5051 
5052 /*@C
5053   MatGetRowMax - Gets the maximum value (of the real part) of each
5054   row of the matrix
5055 
5056   Logically Collective
5057 
5058   Input Parameter:
5059 . mat - the matrix
5060 
5061   Output Parameters:
5062 + v   - the vector for storing the maximums
5063 - idx - the indices of the column found for each row (optional)
5064 
5065   Level: intermediate
5066 
5067   Notes:
5068   The result of this call are the same as if one converted the matrix to dense format
5069   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5070 
5071   This code is only implemented for a couple of matrix formats.
5072 
5073 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5074 @*/
5075 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5076 {
5077   PetscFunctionBegin;
5078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5079   PetscValidType(mat, 1);
5080   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5081   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5082 
5083   if (!mat->cmap->N) {
5084     PetscCall(VecSet(v, PETSC_MIN_REAL));
5085     if (idx) {
5086       PetscInt i, m = mat->rmap->n;
5087       for (i = 0; i < m; i++) idx[i] = -1;
5088     }
5089   } else {
5090     MatCheckPreallocated(mat, 1);
5091     PetscUseTypeMethod(mat, getrowmax, v, idx);
5092   }
5093   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5094   PetscFunctionReturn(PETSC_SUCCESS);
5095 }
5096 
5097 /*@C
5098   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5099   row of the matrix
5100 
5101   Logically Collective
5102 
5103   Input Parameter:
5104 . mat - the matrix
5105 
5106   Output Parameters:
5107 + v   - the vector for storing the maximums
5108 - idx - the indices of the column found for each row (or `NULL` if not needed)
5109 
5110   Level: intermediate
5111 
5112   Notes:
5113   if a row is completely empty or has only 0.0 values then the `idx` value for that
5114   row is 0 (the first column).
5115 
5116   This code is only implemented for a couple of matrix formats.
5117 
5118 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5119 @*/
5120 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5121 {
5122   PetscFunctionBegin;
5123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5124   PetscValidType(mat, 1);
5125   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5126   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5127 
5128   if (!mat->cmap->N) {
5129     PetscCall(VecSet(v, 0.0));
5130     if (idx) {
5131       PetscInt i, m = mat->rmap->n;
5132       for (i = 0; i < m; i++) idx[i] = -1;
5133     }
5134   } else {
5135     MatCheckPreallocated(mat, 1);
5136     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5137     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5138   }
5139   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5140   PetscFunctionReturn(PETSC_SUCCESS);
5141 }
5142 
5143 /*@
5144   MatGetRowSum - Gets the sum of each row of the matrix
5145 
5146   Logically or Neighborhood Collective
5147 
5148   Input Parameter:
5149 . mat - the matrix
5150 
5151   Output Parameter:
5152 . v - the vector for storing the sum of rows
5153 
5154   Level: intermediate
5155 
5156   Note:
5157   This code is slow since it is not currently specialized for different formats
5158 
5159 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5160 @*/
5161 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5162 {
5163   Vec ones;
5164 
5165   PetscFunctionBegin;
5166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5167   PetscValidType(mat, 1);
5168   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5169   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5170   MatCheckPreallocated(mat, 1);
5171   PetscCall(MatCreateVecs(mat, &ones, NULL));
5172   PetscCall(VecSet(ones, 1.));
5173   PetscCall(MatMult(mat, ones, v));
5174   PetscCall(VecDestroy(&ones));
5175   PetscFunctionReturn(PETSC_SUCCESS);
5176 }
5177 
5178 /*@
5179   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5180   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5181 
5182   Collective
5183 
5184   Input Parameter:
5185 . mat - the matrix to provide the transpose
5186 
5187   Output Parameter:
5188 . 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
5189 
5190   Level: advanced
5191 
5192   Note:
5193   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
5194   routine allows bypassing that call.
5195 
5196 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5197 @*/
5198 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5199 {
5200   PetscContainer  rB = NULL;
5201   MatParentState *rb = NULL;
5202 
5203   PetscFunctionBegin;
5204   PetscCall(PetscNew(&rb));
5205   rb->id    = ((PetscObject)mat)->id;
5206   rb->state = 0;
5207   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5208   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5209   PetscCall(PetscContainerSetPointer(rB, rb));
5210   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5211   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5212   PetscCall(PetscObjectDereference((PetscObject)rB));
5213   PetscFunctionReturn(PETSC_SUCCESS);
5214 }
5215 
5216 /*@
5217   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5218 
5219   Collective
5220 
5221   Input Parameters:
5222 + mat   - the matrix to transpose
5223 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5224 
5225   Output Parameter:
5226 . B - the transpose
5227 
5228   Level: intermediate
5229 
5230   Notes:
5231   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5232 
5233   `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
5234   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5235 
5236   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.
5237 
5238   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5239 
5240   If mat is unchanged from the last call this function returns immediately without recomputing the result
5241 
5242   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5243 
5244 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5245           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5246 @*/
5247 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5248 {
5249   PetscContainer  rB = NULL;
5250   MatParentState *rb = NULL;
5251 
5252   PetscFunctionBegin;
5253   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5254   PetscValidType(mat, 1);
5255   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5256   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5257   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5258   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5259   MatCheckPreallocated(mat, 1);
5260   if (reuse == MAT_REUSE_MATRIX) {
5261     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5262     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5263     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5264     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5265     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5266   }
5267 
5268   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5269   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5270     PetscUseTypeMethod(mat, transpose, reuse, B);
5271     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5272   }
5273   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5274 
5275   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5276   if (reuse != MAT_INPLACE_MATRIX) {
5277     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5278     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5279     rb->state        = ((PetscObject)mat)->state;
5280     rb->nonzerostate = mat->nonzerostate;
5281   }
5282   PetscFunctionReturn(PETSC_SUCCESS);
5283 }
5284 
5285 /*@
5286   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5287 
5288   Collective
5289 
5290   Input Parameter:
5291 . A - the matrix to transpose
5292 
5293   Output Parameter:
5294 . 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
5295       numerical portion.
5296 
5297   Level: intermediate
5298 
5299   Note:
5300   This is not supported for many matrix types, use `MatTranspose()` in those cases
5301 
5302 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5303 @*/
5304 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5305 {
5306   PetscFunctionBegin;
5307   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5308   PetscValidType(A, 1);
5309   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5310   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5311   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5312   PetscUseTypeMethod(A, transposesymbolic, B);
5313   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5314 
5315   PetscCall(MatTransposeSetPrecursor(A, *B));
5316   PetscFunctionReturn(PETSC_SUCCESS);
5317 }
5318 
5319 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5320 {
5321   PetscContainer  rB;
5322   MatParentState *rb;
5323 
5324   PetscFunctionBegin;
5325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5326   PetscValidType(A, 1);
5327   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5328   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5329   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5330   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5331   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5332   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5333   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5334   PetscFunctionReturn(PETSC_SUCCESS);
5335 }
5336 
5337 /*@
5338   MatIsTranspose - Test whether a matrix is another one's transpose,
5339   or its own, in which case it tests symmetry.
5340 
5341   Collective
5342 
5343   Input Parameters:
5344 + A   - the matrix to test
5345 . B   - the matrix to test against, this can equal the first parameter
5346 - tol - tolerance, differences between entries smaller than this are counted as zero
5347 
5348   Output Parameter:
5349 . flg - the result
5350 
5351   Level: intermediate
5352 
5353   Notes:
5354   Only available for `MATAIJ` matrices.
5355 
5356   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5357   test involves parallel copies of the block off-diagonal parts of the matrix.
5358 
5359 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5360 @*/
5361 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5362 {
5363   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5364 
5365   PetscFunctionBegin;
5366   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5367   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5368   PetscAssertPointer(flg, 4);
5369   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5370   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5371   *flg = PETSC_FALSE;
5372   if (f && g) {
5373     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5374     PetscCall((*f)(A, B, tol, flg));
5375   } else {
5376     MatType mattype;
5377 
5378     PetscCall(MatGetType(f ? B : A, &mattype));
5379     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5380   }
5381   PetscFunctionReturn(PETSC_SUCCESS);
5382 }
5383 
5384 /*@
5385   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5386 
5387   Collective
5388 
5389   Input Parameters:
5390 + mat   - the matrix to transpose and complex conjugate
5391 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5392 
5393   Output Parameter:
5394 . B - the Hermitian transpose
5395 
5396   Level: intermediate
5397 
5398 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5399 @*/
5400 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5401 {
5402   PetscFunctionBegin;
5403   PetscCall(MatTranspose(mat, reuse, B));
5404 #if defined(PETSC_USE_COMPLEX)
5405   PetscCall(MatConjugate(*B));
5406 #endif
5407   PetscFunctionReturn(PETSC_SUCCESS);
5408 }
5409 
5410 /*@
5411   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5412 
5413   Collective
5414 
5415   Input Parameters:
5416 + A   - the matrix to test
5417 . B   - the matrix to test against, this can equal the first parameter
5418 - tol - tolerance, differences between entries smaller than this are counted as zero
5419 
5420   Output Parameter:
5421 . flg - the result
5422 
5423   Level: intermediate
5424 
5425   Notes:
5426   Only available for `MATAIJ` matrices.
5427 
5428   The sequential algorithm
5429   has a running time of the order of the number of nonzeros; the parallel
5430   test involves parallel copies of the block off-diagonal parts of the matrix.
5431 
5432 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5433 @*/
5434 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5435 {
5436   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5437 
5438   PetscFunctionBegin;
5439   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5440   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5441   PetscAssertPointer(flg, 4);
5442   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5443   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5444   if (f && g) {
5445     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5446     PetscCall((*f)(A, B, tol, flg));
5447   }
5448   PetscFunctionReturn(PETSC_SUCCESS);
5449 }
5450 
5451 /*@
5452   MatPermute - Creates a new matrix with rows and columns permuted from the
5453   original.
5454 
5455   Collective
5456 
5457   Input Parameters:
5458 + mat - the matrix to permute
5459 . row - row permutation, each processor supplies only the permutation for its rows
5460 - col - column permutation, each processor supplies only the permutation for its columns
5461 
5462   Output Parameter:
5463 . B - the permuted matrix
5464 
5465   Level: advanced
5466 
5467   Note:
5468   The index sets map from row/col of permuted matrix to row/col of original matrix.
5469   The index sets should be on the same communicator as mat and have the same local sizes.
5470 
5471   Developer Note:
5472   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5473   exploit the fact that row and col are permutations, consider implementing the
5474   more general `MatCreateSubMatrix()` instead.
5475 
5476 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5477 @*/
5478 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5479 {
5480   PetscFunctionBegin;
5481   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5482   PetscValidType(mat, 1);
5483   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5484   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5485   PetscAssertPointer(B, 4);
5486   PetscCheckSameComm(mat, 1, row, 2);
5487   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5488   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5489   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5490   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5491   MatCheckPreallocated(mat, 1);
5492 
5493   if (mat->ops->permute) {
5494     PetscUseTypeMethod(mat, permute, row, col, B);
5495     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5496   } else {
5497     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5498   }
5499   PetscFunctionReturn(PETSC_SUCCESS);
5500 }
5501 
5502 /*@
5503   MatEqual - Compares two matrices.
5504 
5505   Collective
5506 
5507   Input Parameters:
5508 + A - the first matrix
5509 - B - the second matrix
5510 
5511   Output Parameter:
5512 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5513 
5514   Level: intermediate
5515 
5516 .seealso: [](ch_matrices), `Mat`
5517 @*/
5518 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5519 {
5520   PetscFunctionBegin;
5521   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5522   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5523   PetscValidType(A, 1);
5524   PetscValidType(B, 2);
5525   PetscAssertPointer(flg, 3);
5526   PetscCheckSameComm(A, 1, B, 2);
5527   MatCheckPreallocated(A, 1);
5528   MatCheckPreallocated(B, 2);
5529   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5530   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5531   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,
5532              B->cmap->N);
5533   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5534     PetscUseTypeMethod(A, equal, B, flg);
5535   } else {
5536     PetscCall(MatMultEqual(A, B, 10, flg));
5537   }
5538   PetscFunctionReturn(PETSC_SUCCESS);
5539 }
5540 
5541 /*@
5542   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5543   matrices that are stored as vectors.  Either of the two scaling
5544   matrices can be `NULL`.
5545 
5546   Collective
5547 
5548   Input Parameters:
5549 + mat - the matrix to be scaled
5550 . l   - the left scaling vector (or `NULL`)
5551 - r   - the right scaling vector (or `NULL`)
5552 
5553   Level: intermediate
5554 
5555   Note:
5556   `MatDiagonalScale()` computes $A = LAR$, where
5557   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5558   The L scales the rows of the matrix, the R scales the columns of the matrix.
5559 
5560 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5561 @*/
5562 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5563 {
5564   PetscFunctionBegin;
5565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5566   PetscValidType(mat, 1);
5567   if (l) {
5568     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5569     PetscCheckSameComm(mat, 1, l, 2);
5570   }
5571   if (r) {
5572     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5573     PetscCheckSameComm(mat, 1, r, 3);
5574   }
5575   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5576   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5577   MatCheckPreallocated(mat, 1);
5578   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5579 
5580   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5581   PetscUseTypeMethod(mat, diagonalscale, l, r);
5582   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5583   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5584   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5585   PetscFunctionReturn(PETSC_SUCCESS);
5586 }
5587 
5588 /*@
5589   MatScale - Scales all elements of a matrix by a given number.
5590 
5591   Logically Collective
5592 
5593   Input Parameters:
5594 + mat - the matrix to be scaled
5595 - a   - the scaling value
5596 
5597   Level: intermediate
5598 
5599 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5600 @*/
5601 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5602 {
5603   PetscFunctionBegin;
5604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5605   PetscValidType(mat, 1);
5606   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5607   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5608   PetscValidLogicalCollectiveScalar(mat, a, 2);
5609   MatCheckPreallocated(mat, 1);
5610 
5611   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5612   if (a != (PetscScalar)1.0) {
5613     PetscUseTypeMethod(mat, scale, a);
5614     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5615   }
5616   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5617   PetscFunctionReturn(PETSC_SUCCESS);
5618 }
5619 
5620 /*@
5621   MatNorm - Calculates various norms of a matrix.
5622 
5623   Collective
5624 
5625   Input Parameters:
5626 + mat  - the matrix
5627 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5628 
5629   Output Parameter:
5630 . nrm - the resulting norm
5631 
5632   Level: intermediate
5633 
5634 .seealso: [](ch_matrices), `Mat`
5635 @*/
5636 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5637 {
5638   PetscFunctionBegin;
5639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5640   PetscValidType(mat, 1);
5641   PetscAssertPointer(nrm, 3);
5642 
5643   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5644   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5645   MatCheckPreallocated(mat, 1);
5646 
5647   PetscUseTypeMethod(mat, norm, type, nrm);
5648   PetscFunctionReturn(PETSC_SUCCESS);
5649 }
5650 
5651 /*
5652      This variable is used to prevent counting of MatAssemblyBegin() that
5653    are called from within a MatAssemblyEnd().
5654 */
5655 static PetscInt MatAssemblyEnd_InUse = 0;
5656 /*@
5657   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5658   be called after completing all calls to `MatSetValues()`.
5659 
5660   Collective
5661 
5662   Input Parameters:
5663 + mat  - the matrix
5664 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5665 
5666   Level: beginner
5667 
5668   Notes:
5669   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5670   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5671 
5672   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5673   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5674   using the matrix.
5675 
5676   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5677   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
5678   a global collective operation requiring all processes that share the matrix.
5679 
5680   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5681   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5682   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5683 
5684 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5685 @*/
5686 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5687 {
5688   PetscFunctionBegin;
5689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5690   PetscValidType(mat, 1);
5691   MatCheckPreallocated(mat, 1);
5692   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5693   if (mat->assembled) {
5694     mat->was_assembled = PETSC_TRUE;
5695     mat->assembled     = PETSC_FALSE;
5696   }
5697 
5698   if (!MatAssemblyEnd_InUse) {
5699     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5700     PetscTryTypeMethod(mat, assemblybegin, type);
5701     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5702   } else PetscTryTypeMethod(mat, assemblybegin, type);
5703   PetscFunctionReturn(PETSC_SUCCESS);
5704 }
5705 
5706 /*@
5707   MatAssembled - Indicates if a matrix has been assembled and is ready for
5708   use; for example, in matrix-vector product.
5709 
5710   Not Collective
5711 
5712   Input Parameter:
5713 . mat - the matrix
5714 
5715   Output Parameter:
5716 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5717 
5718   Level: advanced
5719 
5720 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5721 @*/
5722 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5723 {
5724   PetscFunctionBegin;
5725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5726   PetscAssertPointer(assembled, 2);
5727   *assembled = mat->assembled;
5728   PetscFunctionReturn(PETSC_SUCCESS);
5729 }
5730 
5731 /*@
5732   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5733   be called after `MatAssemblyBegin()`.
5734 
5735   Collective
5736 
5737   Input Parameters:
5738 + mat  - the matrix
5739 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5740 
5741   Options Database Keys:
5742 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5743 . -mat_view ::ascii_info_detail      - Prints more detailed info
5744 . -mat_view                          - Prints matrix in ASCII format
5745 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5746 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5747 . -display <name>                    - Sets display name (default is host)
5748 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5749 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5750 . -viewer_socket_machine <machine>   - Machine to use for socket
5751 . -viewer_socket_port <port>         - Port number to use for socket
5752 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5753 
5754   Level: beginner
5755 
5756 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5757 @*/
5758 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5759 {
5760   static PetscInt inassm = 0;
5761   PetscBool       flg    = PETSC_FALSE;
5762 
5763   PetscFunctionBegin;
5764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5765   PetscValidType(mat, 1);
5766 
5767   inassm++;
5768   MatAssemblyEnd_InUse++;
5769   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5770     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5771     PetscTryTypeMethod(mat, assemblyend, type);
5772     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5773   } else PetscTryTypeMethod(mat, assemblyend, type);
5774 
5775   /* Flush assembly is not a true assembly */
5776   if (type != MAT_FLUSH_ASSEMBLY) {
5777     if (mat->num_ass) {
5778       if (!mat->symmetry_eternal) {
5779         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5780         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5781       }
5782       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5783       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5784     }
5785     mat->num_ass++;
5786     mat->assembled        = PETSC_TRUE;
5787     mat->ass_nonzerostate = mat->nonzerostate;
5788   }
5789 
5790   mat->insertmode = NOT_SET_VALUES;
5791   MatAssemblyEnd_InUse--;
5792   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5793   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5794     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5795 
5796     if (mat->checksymmetryonassembly) {
5797       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5798       if (flg) {
5799         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5800       } else {
5801         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5802       }
5803     }
5804     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5805   }
5806   inassm--;
5807   PetscFunctionReturn(PETSC_SUCCESS);
5808 }
5809 
5810 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5811 /*@
5812   MatSetOption - Sets a parameter option for a matrix. Some options
5813   may be specific to certain storage formats.  Some options
5814   determine how values will be inserted (or added). Sorted,
5815   row-oriented input will generally assemble the fastest. The default
5816   is row-oriented.
5817 
5818   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5819 
5820   Input Parameters:
5821 + mat - the matrix
5822 . op  - the option, one of those listed below (and possibly others),
5823 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5824 
5825   Options Describing Matrix Structure:
5826 + `MAT_SPD`                         - symmetric positive definite
5827 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5828 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5829 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5830 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5831 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5832 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5833 
5834    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5835    do not need to be computed (usually at a high cost)
5836 
5837    Options For Use with `MatSetValues()`:
5838    Insert a logically dense subblock, which can be
5839 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5840 
5841    These options reflect the data you pass in with `MatSetValues()`; it has
5842    nothing to do with how the data is stored internally in the matrix
5843    data structure.
5844 
5845    When (re)assembling a matrix, we can restrict the input for
5846    efficiency/debugging purposes.  These options include
5847 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5848 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5849 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5850 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5851 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5852 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5853         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5854         performance for very large process counts.
5855 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5856         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5857         functions, instead sending only neighbor messages.
5858 
5859   Level: intermediate
5860 
5861   Notes:
5862   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5863 
5864   Some options are relevant only for particular matrix types and
5865   are thus ignored by others.  Other options are not supported by
5866   certain matrix types and will generate an error message if set.
5867 
5868   If using Fortran to compute a matrix, one may need to
5869   use the column-oriented option (or convert to the row-oriented
5870   format).
5871 
5872   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5873   that would generate a new entry in the nonzero structure is instead
5874   ignored.  Thus, if memory has not already been allocated for this particular
5875   data, then the insertion is ignored. For dense matrices, in which
5876   the entire array is allocated, no entries are ever ignored.
5877   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5878 
5879   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5880   that would generate a new entry in the nonzero structure instead produces
5881   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
5882 
5883   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5884   that would generate a new entry that has not been preallocated will
5885   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5886   only.) This is a useful flag when debugging matrix memory preallocation.
5887   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5888 
5889   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5890   other processors should be dropped, rather than stashed.
5891   This is useful if you know that the "owning" processor is also
5892   always generating the correct matrix entries, so that PETSc need
5893   not transfer duplicate entries generated on another processor.
5894 
5895   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5896   searches during matrix assembly. When this flag is set, the hash table
5897   is created during the first matrix assembly. This hash table is
5898   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5899   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5900   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5901   supported by `MATMPIBAIJ` format only.
5902 
5903   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5904   are kept in the nonzero structure
5905 
5906   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5907   a zero location in the matrix
5908 
5909   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5910 
5911   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5912   zero row routines and thus improves performance for very large process counts.
5913 
5914   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5915   part of the matrix (since they should match the upper triangular part).
5916 
5917   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5918   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5919   with finite difference schemes with non-periodic boundary conditions.
5920 
5921   Developer Note:
5922   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5923   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5924   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5925   not changed.
5926 
5927 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5928 @*/
5929 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5930 {
5931   PetscFunctionBegin;
5932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5933   if (op > 0) {
5934     PetscValidLogicalCollectiveEnum(mat, op, 2);
5935     PetscValidLogicalCollectiveBool(mat, flg, 3);
5936   }
5937 
5938   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);
5939 
5940   switch (op) {
5941   case MAT_FORCE_DIAGONAL_ENTRIES:
5942     mat->force_diagonals = flg;
5943     PetscFunctionReturn(PETSC_SUCCESS);
5944   case MAT_NO_OFF_PROC_ENTRIES:
5945     mat->nooffprocentries = flg;
5946     PetscFunctionReturn(PETSC_SUCCESS);
5947   case MAT_SUBSET_OFF_PROC_ENTRIES:
5948     mat->assembly_subset = flg;
5949     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5950 #if !defined(PETSC_HAVE_MPIUNI)
5951       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5952 #endif
5953       mat->stash.first_assembly_done = PETSC_FALSE;
5954     }
5955     PetscFunctionReturn(PETSC_SUCCESS);
5956   case MAT_NO_OFF_PROC_ZERO_ROWS:
5957     mat->nooffproczerorows = flg;
5958     PetscFunctionReturn(PETSC_SUCCESS);
5959   case MAT_SPD:
5960     if (flg) {
5961       mat->spd                    = PETSC_BOOL3_TRUE;
5962       mat->symmetric              = PETSC_BOOL3_TRUE;
5963       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5964     } else {
5965       mat->spd = PETSC_BOOL3_FALSE;
5966     }
5967     break;
5968   case MAT_SYMMETRIC:
5969     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5970     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5971 #if !defined(PETSC_USE_COMPLEX)
5972     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5973 #endif
5974     break;
5975   case MAT_HERMITIAN:
5976     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5977     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5978 #if !defined(PETSC_USE_COMPLEX)
5979     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5980 #endif
5981     break;
5982   case MAT_STRUCTURALLY_SYMMETRIC:
5983     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5984     break;
5985   case MAT_SYMMETRY_ETERNAL:
5986     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");
5987     mat->symmetry_eternal = flg;
5988     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5989     break;
5990   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5991     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");
5992     mat->structural_symmetry_eternal = flg;
5993     break;
5994   case MAT_SPD_ETERNAL:
5995     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");
5996     mat->spd_eternal = flg;
5997     if (flg) {
5998       mat->structural_symmetry_eternal = PETSC_TRUE;
5999       mat->symmetry_eternal            = PETSC_TRUE;
6000     }
6001     break;
6002   case MAT_STRUCTURE_ONLY:
6003     mat->structure_only = flg;
6004     break;
6005   case MAT_SORTED_FULL:
6006     mat->sortedfull = flg;
6007     break;
6008   default:
6009     break;
6010   }
6011   PetscTryTypeMethod(mat, setoption, op, flg);
6012   PetscFunctionReturn(PETSC_SUCCESS);
6013 }
6014 
6015 /*@
6016   MatGetOption - Gets a parameter option that has been set for a matrix.
6017 
6018   Logically Collective
6019 
6020   Input Parameters:
6021 + mat - the matrix
6022 - op  - the option, this only responds to certain options, check the code for which ones
6023 
6024   Output Parameter:
6025 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6026 
6027   Level: intermediate
6028 
6029   Notes:
6030   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6031 
6032   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6033   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6034 
6035 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6036     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6037 @*/
6038 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6039 {
6040   PetscFunctionBegin;
6041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6042   PetscValidType(mat, 1);
6043 
6044   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);
6045   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()");
6046 
6047   switch (op) {
6048   case MAT_NO_OFF_PROC_ENTRIES:
6049     *flg = mat->nooffprocentries;
6050     break;
6051   case MAT_NO_OFF_PROC_ZERO_ROWS:
6052     *flg = mat->nooffproczerorows;
6053     break;
6054   case MAT_SYMMETRIC:
6055     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6056     break;
6057   case MAT_HERMITIAN:
6058     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6059     break;
6060   case MAT_STRUCTURALLY_SYMMETRIC:
6061     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6062     break;
6063   case MAT_SPD:
6064     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6065     break;
6066   case MAT_SYMMETRY_ETERNAL:
6067     *flg = mat->symmetry_eternal;
6068     break;
6069   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6070     *flg = mat->symmetry_eternal;
6071     break;
6072   default:
6073     break;
6074   }
6075   PetscFunctionReturn(PETSC_SUCCESS);
6076 }
6077 
6078 /*@
6079   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6080   this routine retains the old nonzero structure.
6081 
6082   Logically Collective
6083 
6084   Input Parameter:
6085 . mat - the matrix
6086 
6087   Level: intermediate
6088 
6089   Note:
6090   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.
6091   See the Performance chapter of the users manual for information on preallocating matrices.
6092 
6093 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6094 @*/
6095 PetscErrorCode MatZeroEntries(Mat mat)
6096 {
6097   PetscFunctionBegin;
6098   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6099   PetscValidType(mat, 1);
6100   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6101   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");
6102   MatCheckPreallocated(mat, 1);
6103 
6104   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6105   PetscUseTypeMethod(mat, zeroentries);
6106   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6107   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6108   PetscFunctionReturn(PETSC_SUCCESS);
6109 }
6110 
6111 /*@
6112   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6113   of a set of rows and columns of a matrix.
6114 
6115   Collective
6116 
6117   Input Parameters:
6118 + mat     - the matrix
6119 . numRows - the number of rows/columns to zero
6120 . rows    - the global row indices
6121 . diag    - value put in the diagonal of the eliminated rows
6122 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6123 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6124 
6125   Level: intermediate
6126 
6127   Notes:
6128   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6129 
6130   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6131   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
6132 
6133   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6134   Krylov method to take advantage of the known solution on the zeroed rows.
6135 
6136   For the parallel case, all processes that share the matrix (i.e.,
6137   those in the communicator used for matrix creation) MUST call this
6138   routine, regardless of whether any rows being zeroed are owned by
6139   them.
6140 
6141   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6142 
6143   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6144   list only rows local to itself).
6145 
6146   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6147 
6148 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6149           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6150 @*/
6151 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6152 {
6153   PetscFunctionBegin;
6154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6155   PetscValidType(mat, 1);
6156   if (numRows) PetscAssertPointer(rows, 3);
6157   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6158   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6159   MatCheckPreallocated(mat, 1);
6160 
6161   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6162   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6163   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6164   PetscFunctionReturn(PETSC_SUCCESS);
6165 }
6166 
6167 /*@
6168   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6169   of a set of rows and columns of a matrix.
6170 
6171   Collective
6172 
6173   Input Parameters:
6174 + mat  - the matrix
6175 . is   - the rows to zero
6176 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6177 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6178 - b    - optional vector of right hand side, that will be adjusted by provided solution
6179 
6180   Level: intermediate
6181 
6182   Note:
6183   See `MatZeroRowsColumns()` for details on how this routine operates.
6184 
6185 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6186           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6187 @*/
6188 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6189 {
6190   PetscInt        numRows;
6191   const PetscInt *rows;
6192 
6193   PetscFunctionBegin;
6194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6195   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6196   PetscValidType(mat, 1);
6197   PetscValidType(is, 2);
6198   PetscCall(ISGetLocalSize(is, &numRows));
6199   PetscCall(ISGetIndices(is, &rows));
6200   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6201   PetscCall(ISRestoreIndices(is, &rows));
6202   PetscFunctionReturn(PETSC_SUCCESS);
6203 }
6204 
6205 /*@
6206   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6207   of a set of rows of a matrix.
6208 
6209   Collective
6210 
6211   Input Parameters:
6212 + mat     - the matrix
6213 . numRows - the number of rows to zero
6214 . rows    - the global row indices
6215 . diag    - value put in the diagonal of the zeroed rows
6216 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6217 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6218 
6219   Level: intermediate
6220 
6221   Notes:
6222   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6223 
6224   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6225 
6226   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6227   Krylov method to take advantage of the known solution on the zeroed rows.
6228 
6229   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)
6230   from the matrix.
6231 
6232   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6233   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
6234   formats this does not alter the nonzero structure.
6235 
6236   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6237   of the matrix is not changed the values are
6238   merely zeroed.
6239 
6240   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6241   formats can optionally remove the main diagonal entry from the
6242   nonzero structure as well, by passing 0.0 as the final argument).
6243 
6244   For the parallel case, all processes that share the matrix (i.e.,
6245   those in the communicator used for matrix creation) MUST call this
6246   routine, regardless of whether any rows being zeroed are owned by
6247   them.
6248 
6249   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6250   list only rows local to itself).
6251 
6252   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6253   owns that are to be zeroed. This saves a global synchronization in the implementation.
6254 
6255 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6256           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6257 @*/
6258 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6259 {
6260   PetscFunctionBegin;
6261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6262   PetscValidType(mat, 1);
6263   if (numRows) PetscAssertPointer(rows, 3);
6264   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6265   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6266   MatCheckPreallocated(mat, 1);
6267 
6268   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6269   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6270   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6271   PetscFunctionReturn(PETSC_SUCCESS);
6272 }
6273 
6274 /*@
6275   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6276   of a set of rows of a matrix.
6277 
6278   Collective
6279 
6280   Input Parameters:
6281 + mat  - the matrix
6282 . is   - index set of rows to remove (if `NULL` then no row is removed)
6283 . diag - value put in all diagonals of eliminated rows
6284 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6285 - b    - optional vector of right hand side, that will be adjusted by provided solution
6286 
6287   Level: intermediate
6288 
6289   Note:
6290   See `MatZeroRows()` for details on how this routine operates.
6291 
6292 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6293           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6294 @*/
6295 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6296 {
6297   PetscInt        numRows = 0;
6298   const PetscInt *rows    = NULL;
6299 
6300   PetscFunctionBegin;
6301   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6302   PetscValidType(mat, 1);
6303   if (is) {
6304     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6305     PetscCall(ISGetLocalSize(is, &numRows));
6306     PetscCall(ISGetIndices(is, &rows));
6307   }
6308   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6309   if (is) PetscCall(ISRestoreIndices(is, &rows));
6310   PetscFunctionReturn(PETSC_SUCCESS);
6311 }
6312 
6313 /*@
6314   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6315   of a set of rows of a matrix. These rows must be local to the process.
6316 
6317   Collective
6318 
6319   Input Parameters:
6320 + mat     - the matrix
6321 . numRows - the number of rows to remove
6322 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6323 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6324 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6325 - b       - optional vector of right hand side, that will be adjusted by provided solution
6326 
6327   Level: intermediate
6328 
6329   Notes:
6330   See `MatZeroRows()` for details on how this routine operates.
6331 
6332   The grid coordinates are across the entire grid, not just the local portion
6333 
6334   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6335   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6336   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6337   `DM_BOUNDARY_PERIODIC` boundary type.
6338 
6339   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
6340   a single value per point) you can skip filling those indices.
6341 
6342   Fortran Note:
6343   `idxm` and `idxn` should be declared as
6344 $     MatStencil idxm(4, m)
6345   and the values inserted using
6346 .vb
6347     idxm(MatStencil_i, 1) = i
6348     idxm(MatStencil_j, 1) = j
6349     idxm(MatStencil_k, 1) = k
6350     idxm(MatStencil_c, 1) = c
6351    etc
6352 .ve
6353 
6354 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6355           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6356 @*/
6357 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6358 {
6359   PetscInt  dim    = mat->stencil.dim;
6360   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6361   PetscInt *dims   = mat->stencil.dims + 1;
6362   PetscInt *starts = mat->stencil.starts;
6363   PetscInt *dxm    = (PetscInt *)rows;
6364   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6365 
6366   PetscFunctionBegin;
6367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6368   PetscValidType(mat, 1);
6369   if (numRows) PetscAssertPointer(rows, 3);
6370 
6371   PetscCall(PetscMalloc1(numRows, &jdxm));
6372   for (i = 0; i < numRows; ++i) {
6373     /* Skip unused dimensions (they are ordered k, j, i, c) */
6374     for (j = 0; j < 3 - sdim; ++j) dxm++;
6375     /* Local index in X dir */
6376     tmp = *dxm++ - starts[0];
6377     /* Loop over remaining dimensions */
6378     for (j = 0; j < dim - 1; ++j) {
6379       /* If nonlocal, set index to be negative */
6380       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6381       /* Update local index */
6382       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6383     }
6384     /* Skip component slot if necessary */
6385     if (mat->stencil.noc) dxm++;
6386     /* Local row number */
6387     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6388   }
6389   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6390   PetscCall(PetscFree(jdxm));
6391   PetscFunctionReturn(PETSC_SUCCESS);
6392 }
6393 
6394 /*@
6395   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6396   of a set of rows and columns of a matrix.
6397 
6398   Collective
6399 
6400   Input Parameters:
6401 + mat     - the matrix
6402 . numRows - the number of rows/columns to remove
6403 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6404 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6405 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6406 - b       - optional vector of right hand side, that will be adjusted by provided solution
6407 
6408   Level: intermediate
6409 
6410   Notes:
6411   See `MatZeroRowsColumns()` for details on how this routine operates.
6412 
6413   The grid coordinates are across the entire grid, not just the local portion
6414 
6415   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6416   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6417   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6418   `DM_BOUNDARY_PERIODIC` boundary type.
6419 
6420   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
6421   a single value per point) you can skip filling those indices.
6422 
6423   Fortran Note:
6424   `idxm` and `idxn` should be declared as
6425 $     MatStencil idxm(4, m)
6426   and the values inserted using
6427 .vb
6428     idxm(MatStencil_i, 1) = i
6429     idxm(MatStencil_j, 1) = j
6430     idxm(MatStencil_k, 1) = k
6431     idxm(MatStencil_c, 1) = c
6432     etc
6433 .ve
6434 
6435 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6436           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6437 @*/
6438 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6439 {
6440   PetscInt  dim    = mat->stencil.dim;
6441   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6442   PetscInt *dims   = mat->stencil.dims + 1;
6443   PetscInt *starts = mat->stencil.starts;
6444   PetscInt *dxm    = (PetscInt *)rows;
6445   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6446 
6447   PetscFunctionBegin;
6448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6449   PetscValidType(mat, 1);
6450   if (numRows) PetscAssertPointer(rows, 3);
6451 
6452   PetscCall(PetscMalloc1(numRows, &jdxm));
6453   for (i = 0; i < numRows; ++i) {
6454     /* Skip unused dimensions (they are ordered k, j, i, c) */
6455     for (j = 0; j < 3 - sdim; ++j) dxm++;
6456     /* Local index in X dir */
6457     tmp = *dxm++ - starts[0];
6458     /* Loop over remaining dimensions */
6459     for (j = 0; j < dim - 1; ++j) {
6460       /* If nonlocal, set index to be negative */
6461       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6462       /* Update local index */
6463       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6464     }
6465     /* Skip component slot if necessary */
6466     if (mat->stencil.noc) dxm++;
6467     /* Local row number */
6468     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6469   }
6470   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6471   PetscCall(PetscFree(jdxm));
6472   PetscFunctionReturn(PETSC_SUCCESS);
6473 }
6474 
6475 /*@C
6476   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6477   of a set of rows of a matrix; using local numbering of rows.
6478 
6479   Collective
6480 
6481   Input Parameters:
6482 + mat     - the matrix
6483 . numRows - the number of rows to remove
6484 . rows    - the local row indices
6485 . diag    - value put in all diagonals of eliminated rows
6486 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6487 - b       - optional vector of right hand side, that will be adjusted by provided solution
6488 
6489   Level: intermediate
6490 
6491   Notes:
6492   Before calling `MatZeroRowsLocal()`, the user must first set the
6493   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6494 
6495   See `MatZeroRows()` for details on how this routine operates.
6496 
6497 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6498           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6499 @*/
6500 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6501 {
6502   PetscFunctionBegin;
6503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6504   PetscValidType(mat, 1);
6505   if (numRows) PetscAssertPointer(rows, 3);
6506   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6507   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6508   MatCheckPreallocated(mat, 1);
6509 
6510   if (mat->ops->zerorowslocal) {
6511     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6512   } else {
6513     IS              is, newis;
6514     const PetscInt *newRows;
6515 
6516     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6517     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6518     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6519     PetscCall(ISGetIndices(newis, &newRows));
6520     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6521     PetscCall(ISRestoreIndices(newis, &newRows));
6522     PetscCall(ISDestroy(&newis));
6523     PetscCall(ISDestroy(&is));
6524   }
6525   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6526   PetscFunctionReturn(PETSC_SUCCESS);
6527 }
6528 
6529 /*@
6530   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6531   of a set of rows of a matrix; using local numbering of rows.
6532 
6533   Collective
6534 
6535   Input Parameters:
6536 + mat  - the matrix
6537 . is   - index set of rows to remove
6538 . diag - value put in all diagonals of eliminated rows
6539 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6540 - b    - optional vector of right hand side, that will be adjusted by provided solution
6541 
6542   Level: intermediate
6543 
6544   Notes:
6545   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6546   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6547 
6548   See `MatZeroRows()` for details on how this routine operates.
6549 
6550 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6551           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6552 @*/
6553 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6554 {
6555   PetscInt        numRows;
6556   const PetscInt *rows;
6557 
6558   PetscFunctionBegin;
6559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6560   PetscValidType(mat, 1);
6561   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6562   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6563   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6564   MatCheckPreallocated(mat, 1);
6565 
6566   PetscCall(ISGetLocalSize(is, &numRows));
6567   PetscCall(ISGetIndices(is, &rows));
6568   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6569   PetscCall(ISRestoreIndices(is, &rows));
6570   PetscFunctionReturn(PETSC_SUCCESS);
6571 }
6572 
6573 /*@
6574   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6575   of a set of rows and columns of a matrix; using local numbering of rows.
6576 
6577   Collective
6578 
6579   Input Parameters:
6580 + mat     - the matrix
6581 . numRows - the number of rows to remove
6582 . rows    - the global row indices
6583 . diag    - value put in all diagonals of eliminated rows
6584 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6585 - b       - optional vector of right hand side, that will be adjusted by provided solution
6586 
6587   Level: intermediate
6588 
6589   Notes:
6590   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6591   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6592 
6593   See `MatZeroRowsColumns()` for details on how this routine operates.
6594 
6595 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6596           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6597 @*/
6598 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6599 {
6600   IS              is, newis;
6601   const PetscInt *newRows;
6602 
6603   PetscFunctionBegin;
6604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6605   PetscValidType(mat, 1);
6606   if (numRows) PetscAssertPointer(rows, 3);
6607   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6608   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6609   MatCheckPreallocated(mat, 1);
6610 
6611   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6612   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6613   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6614   PetscCall(ISGetIndices(newis, &newRows));
6615   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6616   PetscCall(ISRestoreIndices(newis, &newRows));
6617   PetscCall(ISDestroy(&newis));
6618   PetscCall(ISDestroy(&is));
6619   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6620   PetscFunctionReturn(PETSC_SUCCESS);
6621 }
6622 
6623 /*@
6624   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6625   of a set of rows and columns of a matrix; using local numbering of rows.
6626 
6627   Collective
6628 
6629   Input Parameters:
6630 + mat  - the matrix
6631 . is   - index set of rows to remove
6632 . diag - value put in all diagonals of eliminated rows
6633 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6634 - b    - optional vector of right hand side, that will be adjusted by provided solution
6635 
6636   Level: intermediate
6637 
6638   Notes:
6639   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6640   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6641 
6642   See `MatZeroRowsColumns()` for details on how this routine operates.
6643 
6644 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6645           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6646 @*/
6647 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6648 {
6649   PetscInt        numRows;
6650   const PetscInt *rows;
6651 
6652   PetscFunctionBegin;
6653   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6654   PetscValidType(mat, 1);
6655   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6656   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6657   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6658   MatCheckPreallocated(mat, 1);
6659 
6660   PetscCall(ISGetLocalSize(is, &numRows));
6661   PetscCall(ISGetIndices(is, &rows));
6662   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6663   PetscCall(ISRestoreIndices(is, &rows));
6664   PetscFunctionReturn(PETSC_SUCCESS);
6665 }
6666 
6667 /*@C
6668   MatGetSize - Returns the numbers of rows and columns in a matrix.
6669 
6670   Not Collective
6671 
6672   Input Parameter:
6673 . mat - the matrix
6674 
6675   Output Parameters:
6676 + m - the number of global rows
6677 - n - the number of global columns
6678 
6679   Level: beginner
6680 
6681   Note:
6682   Both output parameters can be `NULL` on input.
6683 
6684 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6685 @*/
6686 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6687 {
6688   PetscFunctionBegin;
6689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6690   if (m) *m = mat->rmap->N;
6691   if (n) *n = mat->cmap->N;
6692   PetscFunctionReturn(PETSC_SUCCESS);
6693 }
6694 
6695 /*@C
6696   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6697   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6698 
6699   Not Collective
6700 
6701   Input Parameter:
6702 . mat - the matrix
6703 
6704   Output Parameters:
6705 + m - the number of local rows, use `NULL` to not obtain this value
6706 - n - the number of local columns, use `NULL` to not obtain this value
6707 
6708   Level: beginner
6709 
6710 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6711 @*/
6712 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6713 {
6714   PetscFunctionBegin;
6715   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6716   if (m) PetscAssertPointer(m, 2);
6717   if (n) PetscAssertPointer(n, 3);
6718   if (m) *m = mat->rmap->n;
6719   if (n) *n = mat->cmap->n;
6720   PetscFunctionReturn(PETSC_SUCCESS);
6721 }
6722 
6723 /*@C
6724   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6725   vector one multiplies this matrix by that are owned by this processor.
6726 
6727   Not Collective, unless matrix has not been allocated, then collective
6728 
6729   Input Parameter:
6730 . mat - the matrix
6731 
6732   Output Parameters:
6733 + m - the global index of the first local column, use `NULL` to not obtain this value
6734 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6735 
6736   Level: developer
6737 
6738   Note:
6739   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6740   Layouts](sec_matlayout) for details on matrix layouts.
6741 
6742 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6743 @*/
6744 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6745 {
6746   PetscFunctionBegin;
6747   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6748   PetscValidType(mat, 1);
6749   if (m) PetscAssertPointer(m, 2);
6750   if (n) PetscAssertPointer(n, 3);
6751   MatCheckPreallocated(mat, 1);
6752   if (m) *m = mat->cmap->rstart;
6753   if (n) *n = mat->cmap->rend;
6754   PetscFunctionReturn(PETSC_SUCCESS);
6755 }
6756 
6757 /*@C
6758   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6759   this MPI process.
6760 
6761   Not Collective
6762 
6763   Input Parameter:
6764 . mat - the matrix
6765 
6766   Output Parameters:
6767 + m - the global index of the first local row, use `NULL` to not obtain this value
6768 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6769 
6770   Level: beginner
6771 
6772   Note:
6773   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6774   would contain the result of a matrix vector product with this matrix. See [Matrix
6775   Layouts](sec_matlayout) for details on matrix layouts.
6776 
6777 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6778           `PetscLayout`
6779 @*/
6780 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6781 {
6782   PetscFunctionBegin;
6783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6784   PetscValidType(mat, 1);
6785   if (m) PetscAssertPointer(m, 2);
6786   if (n) PetscAssertPointer(n, 3);
6787   MatCheckPreallocated(mat, 1);
6788   if (m) *m = mat->rmap->rstart;
6789   if (n) *n = mat->rmap->rend;
6790   PetscFunctionReturn(PETSC_SUCCESS);
6791 }
6792 
6793 /*@C
6794   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6795   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6796 
6797   Not Collective, unless matrix has not been allocated
6798 
6799   Input Parameter:
6800 . mat - the matrix
6801 
6802   Output Parameter:
6803 . ranges - start of each processors portion plus one more than the total length at the end
6804 
6805   Level: beginner
6806 
6807   Note:
6808   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6809   would contain the result of a matrix vector product with this matrix. See [Matrix
6810   Layouts](sec_matlayout) for details on matrix layouts.
6811 
6812 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6813 @*/
6814 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6815 {
6816   PetscFunctionBegin;
6817   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6818   PetscValidType(mat, 1);
6819   MatCheckPreallocated(mat, 1);
6820   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6821   PetscFunctionReturn(PETSC_SUCCESS);
6822 }
6823 
6824 /*@C
6825   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6826   vector one multiplies this vector by that are owned by each processor.
6827 
6828   Not Collective, unless matrix has not been allocated
6829 
6830   Input Parameter:
6831 . mat - the matrix
6832 
6833   Output Parameter:
6834 . ranges - start of each processors portion plus one more than the total length at the end
6835 
6836   Level: beginner
6837 
6838   Note:
6839   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6840   Layouts](sec_matlayout) for details on matrix layouts.
6841 
6842 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6843 @*/
6844 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6845 {
6846   PetscFunctionBegin;
6847   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6848   PetscValidType(mat, 1);
6849   MatCheckPreallocated(mat, 1);
6850   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6851   PetscFunctionReturn(PETSC_SUCCESS);
6852 }
6853 
6854 /*@C
6855   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6856 
6857   Not Collective
6858 
6859   Input Parameter:
6860 . A - matrix
6861 
6862   Output Parameters:
6863 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6864 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6865 
6866   Level: intermediate
6867 
6868   Note:
6869   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6870   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6871   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6872   details on matrix layouts.
6873 
6874 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6875 @*/
6876 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6877 {
6878   PetscErrorCode (*f)(Mat, IS *, IS *);
6879 
6880   PetscFunctionBegin;
6881   MatCheckPreallocated(A, 1);
6882   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6883   if (f) {
6884     PetscCall((*f)(A, rows, cols));
6885   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6886     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6887     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6888   }
6889   PetscFunctionReturn(PETSC_SUCCESS);
6890 }
6891 
6892 /*@C
6893   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6894   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6895   to complete the factorization.
6896 
6897   Collective
6898 
6899   Input Parameters:
6900 + fact - the factorized matrix obtained with `MatGetFactor()`
6901 . mat  - the matrix
6902 . row  - row permutation
6903 . col  - column permutation
6904 - info - structure containing
6905 .vb
6906       levels - number of levels of fill.
6907       expected fill - as ratio of original fill.
6908       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6909                 missing diagonal entries)
6910 .ve
6911 
6912   Level: developer
6913 
6914   Notes:
6915   See [Matrix Factorization](sec_matfactor) for additional information.
6916 
6917   Most users should employ the `KSP` interface for linear solvers
6918   instead of working directly with matrix algebra routines such as this.
6919   See, e.g., `KSPCreate()`.
6920 
6921   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6922 
6923   Developer Note:
6924   The Fortran interface is not autogenerated as the
6925   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6926 
6927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6928           `MatGetOrdering()`, `MatFactorInfo`
6929 @*/
6930 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6931 {
6932   PetscFunctionBegin;
6933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6934   PetscValidType(mat, 2);
6935   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6936   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6937   PetscAssertPointer(info, 5);
6938   PetscAssertPointer(fact, 1);
6939   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6940   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6941   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6942   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6943   MatCheckPreallocated(mat, 2);
6944 
6945   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6946   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6947   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6948   PetscFunctionReturn(PETSC_SUCCESS);
6949 }
6950 
6951 /*@C
6952   MatICCFactorSymbolic - Performs symbolic incomplete
6953   Cholesky factorization for a symmetric matrix.  Use
6954   `MatCholeskyFactorNumeric()` to complete the factorization.
6955 
6956   Collective
6957 
6958   Input Parameters:
6959 + fact - the factorized matrix obtained with `MatGetFactor()`
6960 . mat  - the matrix to be factored
6961 . perm - row and column permutation
6962 - info - structure containing
6963 .vb
6964       levels - number of levels of fill.
6965       expected fill - as ratio of original fill.
6966 .ve
6967 
6968   Level: developer
6969 
6970   Notes:
6971   Most users should employ the `KSP` interface for linear solvers
6972   instead of working directly with matrix algebra routines such as this.
6973   See, e.g., `KSPCreate()`.
6974 
6975   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
6976 
6977   Developer Note:
6978   The Fortran interface is not autogenerated as the
6979   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6980 
6981 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6982 @*/
6983 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6984 {
6985   PetscFunctionBegin;
6986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6987   PetscValidType(mat, 2);
6988   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6989   PetscAssertPointer(info, 4);
6990   PetscAssertPointer(fact, 1);
6991   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6992   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6993   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6994   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6995   MatCheckPreallocated(mat, 2);
6996 
6997   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6998   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6999   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7000   PetscFunctionReturn(PETSC_SUCCESS);
7001 }
7002 
7003 /*@C
7004   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7005   points to an array of valid matrices, they may be reused to store the new
7006   submatrices.
7007 
7008   Collective
7009 
7010   Input Parameters:
7011 + mat   - the matrix
7012 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7013 . irow  - index set of rows to extract
7014 . icol  - index set of columns to extract
7015 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7016 
7017   Output Parameter:
7018 . submat - the array of submatrices
7019 
7020   Level: advanced
7021 
7022   Notes:
7023   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7024   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7025   to extract a parallel submatrix.
7026 
7027   Some matrix types place restrictions on the row and column
7028   indices, such as that they be sorted or that they be equal to each other.
7029 
7030   The index sets may not have duplicate entries.
7031 
7032   When extracting submatrices from a parallel matrix, each processor can
7033   form a different submatrix by setting the rows and columns of its
7034   individual index sets according to the local submatrix desired.
7035 
7036   When finished using the submatrices, the user should destroy
7037   them with `MatDestroySubMatrices()`.
7038 
7039   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7040   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7041 
7042   This routine creates the matrices in submat; you should NOT create them before
7043   calling it. It also allocates the array of matrix pointers submat.
7044 
7045   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7046   request one row/column in a block, they must request all rows/columns that are in
7047   that block. For example, if the block size is 2 you cannot request just row 0 and
7048   column 0.
7049 
7050   Fortran Note:
7051   The Fortran interface is slightly different from that given below; it
7052   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7053 
7054 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7055 @*/
7056 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7057 {
7058   PetscInt  i;
7059   PetscBool eq;
7060 
7061   PetscFunctionBegin;
7062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7063   PetscValidType(mat, 1);
7064   if (n) {
7065     PetscAssertPointer(irow, 3);
7066     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7067     PetscAssertPointer(icol, 4);
7068     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7069   }
7070   PetscAssertPointer(submat, 6);
7071   if (n && scall == MAT_REUSE_MATRIX) {
7072     PetscAssertPointer(*submat, 6);
7073     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7074   }
7075   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7076   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7077   MatCheckPreallocated(mat, 1);
7078   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7079   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7080   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7081   for (i = 0; i < n; i++) {
7082     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7083     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7084     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7085 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7086     if (mat->boundtocpu && mat->bindingpropagates) {
7087       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7088       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7089     }
7090 #endif
7091   }
7092   PetscFunctionReturn(PETSC_SUCCESS);
7093 }
7094 
7095 /*@C
7096   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7097 
7098   Collective
7099 
7100   Input Parameters:
7101 + mat   - the matrix
7102 . n     - the number of submatrixes to be extracted
7103 . irow  - index set of rows to extract
7104 . icol  - index set of columns to extract
7105 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7106 
7107   Output Parameter:
7108 . submat - the array of submatrices
7109 
7110   Level: advanced
7111 
7112   Note:
7113   This is used by `PCGASM`
7114 
7115 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7116 @*/
7117 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7118 {
7119   PetscInt  i;
7120   PetscBool eq;
7121 
7122   PetscFunctionBegin;
7123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7124   PetscValidType(mat, 1);
7125   if (n) {
7126     PetscAssertPointer(irow, 3);
7127     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7128     PetscAssertPointer(icol, 4);
7129     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7130   }
7131   PetscAssertPointer(submat, 6);
7132   if (n && scall == MAT_REUSE_MATRIX) {
7133     PetscAssertPointer(*submat, 6);
7134     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7135   }
7136   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7137   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7138   MatCheckPreallocated(mat, 1);
7139 
7140   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7141   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7142   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7143   for (i = 0; i < n; i++) {
7144     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7145     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7146   }
7147   PetscFunctionReturn(PETSC_SUCCESS);
7148 }
7149 
7150 /*@C
7151   MatDestroyMatrices - Destroys an array of matrices.
7152 
7153   Collective
7154 
7155   Input Parameters:
7156 + n   - the number of local matrices
7157 - mat - the matrices (this is a pointer to the array of matrices)
7158 
7159   Level: advanced
7160 
7161   Note:
7162   Frees not only the matrices, but also the array that contains the matrices
7163 
7164   Fortran Note:
7165   This does not free the array.
7166 
7167 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7168 @*/
7169 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7170 {
7171   PetscInt i;
7172 
7173   PetscFunctionBegin;
7174   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7175   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7176   PetscAssertPointer(mat, 2);
7177 
7178   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7179 
7180   /* memory is allocated even if n = 0 */
7181   PetscCall(PetscFree(*mat));
7182   PetscFunctionReturn(PETSC_SUCCESS);
7183 }
7184 
7185 /*@C
7186   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7187 
7188   Collective
7189 
7190   Input Parameters:
7191 + n   - the number of local matrices
7192 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7193                        sequence of `MatCreateSubMatrices()`)
7194 
7195   Level: advanced
7196 
7197   Note:
7198   Frees not only the matrices, but also the array that contains the matrices
7199 
7200   Fortran Note:
7201   This does not free the array.
7202 
7203 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7204 @*/
7205 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7206 {
7207   Mat mat0;
7208 
7209   PetscFunctionBegin;
7210   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7211   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7212   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7213   PetscAssertPointer(mat, 2);
7214 
7215   mat0 = (*mat)[0];
7216   if (mat0 && mat0->ops->destroysubmatrices) {
7217     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7218   } else {
7219     PetscCall(MatDestroyMatrices(n, mat));
7220   }
7221   PetscFunctionReturn(PETSC_SUCCESS);
7222 }
7223 
7224 /*@C
7225   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7226 
7227   Collective
7228 
7229   Input Parameter:
7230 . mat - the matrix
7231 
7232   Output Parameter:
7233 . matstruct - the sequential matrix with the nonzero structure of mat
7234 
7235   Level: developer
7236 
7237 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7238 @*/
7239 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7240 {
7241   PetscFunctionBegin;
7242   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7243   PetscAssertPointer(matstruct, 2);
7244 
7245   PetscValidType(mat, 1);
7246   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7247   MatCheckPreallocated(mat, 1);
7248 
7249   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7250   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7251   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7252   PetscFunctionReturn(PETSC_SUCCESS);
7253 }
7254 
7255 /*@C
7256   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7257 
7258   Collective
7259 
7260   Input Parameter:
7261 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7262                        sequence of `MatGetSeqNonzeroStructure()`)
7263 
7264   Level: advanced
7265 
7266   Note:
7267   Frees not only the matrices, but also the array that contains the matrices
7268 
7269 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7270 @*/
7271 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7272 {
7273   PetscFunctionBegin;
7274   PetscAssertPointer(mat, 1);
7275   PetscCall(MatDestroy(mat));
7276   PetscFunctionReturn(PETSC_SUCCESS);
7277 }
7278 
7279 /*@
7280   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7281   replaces the index sets by larger ones that represent submatrices with
7282   additional overlap.
7283 
7284   Collective
7285 
7286   Input Parameters:
7287 + mat - the matrix
7288 . n   - the number of index sets
7289 . is  - the array of index sets (these index sets will changed during the call)
7290 - ov  - the additional overlap requested
7291 
7292   Options Database Key:
7293 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7294 
7295   Level: developer
7296 
7297   Note:
7298   The computed overlap preserves the matrix block sizes when the blocks are square.
7299   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7300   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7301 
7302 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7303 @*/
7304 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7305 {
7306   PetscInt i, bs, cbs;
7307 
7308   PetscFunctionBegin;
7309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7310   PetscValidType(mat, 1);
7311   PetscValidLogicalCollectiveInt(mat, n, 2);
7312   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7313   if (n) {
7314     PetscAssertPointer(is, 3);
7315     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7316   }
7317   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7318   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7319   MatCheckPreallocated(mat, 1);
7320 
7321   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7322   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7323   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7324   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7325   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7326   if (bs == cbs) {
7327     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7328   }
7329   PetscFunctionReturn(PETSC_SUCCESS);
7330 }
7331 
7332 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7333 
7334 /*@
7335   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7336   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7337   additional overlap.
7338 
7339   Collective
7340 
7341   Input Parameters:
7342 + mat - the matrix
7343 . n   - the number of index sets
7344 . is  - the array of index sets (these index sets will changed during the call)
7345 - ov  - the additional overlap requested
7346 
7347   `   Options Database Key:
7348 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7349 
7350   Level: developer
7351 
7352 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7353 @*/
7354 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7355 {
7356   PetscInt i;
7357 
7358   PetscFunctionBegin;
7359   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7360   PetscValidType(mat, 1);
7361   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7362   if (n) {
7363     PetscAssertPointer(is, 3);
7364     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7365   }
7366   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7367   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7368   MatCheckPreallocated(mat, 1);
7369   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7370   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7371   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7372   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7373   PetscFunctionReturn(PETSC_SUCCESS);
7374 }
7375 
7376 /*@
7377   MatGetBlockSize - Returns the matrix block size.
7378 
7379   Not Collective
7380 
7381   Input Parameter:
7382 . mat - the matrix
7383 
7384   Output Parameter:
7385 . bs - block size
7386 
7387   Level: intermediate
7388 
7389   Notes:
7390   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7391 
7392   If the block size has not been set yet this routine returns 1.
7393 
7394 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7395 @*/
7396 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7397 {
7398   PetscFunctionBegin;
7399   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7400   PetscAssertPointer(bs, 2);
7401   *bs = PetscAbs(mat->rmap->bs);
7402   PetscFunctionReturn(PETSC_SUCCESS);
7403 }
7404 
7405 /*@
7406   MatGetBlockSizes - Returns the matrix block row and column sizes.
7407 
7408   Not Collective
7409 
7410   Input Parameter:
7411 . mat - the matrix
7412 
7413   Output Parameters:
7414 + rbs - row block size
7415 - cbs - column block size
7416 
7417   Level: intermediate
7418 
7419   Notes:
7420   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7421   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7422 
7423   If a block size has not been set yet this routine returns 1.
7424 
7425 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7426 @*/
7427 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7428 {
7429   PetscFunctionBegin;
7430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7431   if (rbs) PetscAssertPointer(rbs, 2);
7432   if (cbs) PetscAssertPointer(cbs, 3);
7433   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7434   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7435   PetscFunctionReturn(PETSC_SUCCESS);
7436 }
7437 
7438 /*@
7439   MatSetBlockSize - Sets the matrix block size.
7440 
7441   Logically Collective
7442 
7443   Input Parameters:
7444 + mat - the matrix
7445 - bs  - block size
7446 
7447   Level: intermediate
7448 
7449   Notes:
7450   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7451   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7452 
7453   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7454   is compatible with the matrix local sizes.
7455 
7456 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7457 @*/
7458 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7459 {
7460   PetscFunctionBegin;
7461   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7462   PetscValidLogicalCollectiveInt(mat, bs, 2);
7463   PetscCall(MatSetBlockSizes(mat, bs, bs));
7464   PetscFunctionReturn(PETSC_SUCCESS);
7465 }
7466 
7467 typedef struct {
7468   PetscInt         n;
7469   IS              *is;
7470   Mat             *mat;
7471   PetscObjectState nonzerostate;
7472   Mat              C;
7473 } EnvelopeData;
7474 
7475 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7476 {
7477   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7478   PetscCall(PetscFree(edata->is));
7479   PetscCall(PetscFree(edata));
7480   return PETSC_SUCCESS;
7481 }
7482 
7483 /*@
7484   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7485   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7486 
7487   Collective
7488 
7489   Input Parameter:
7490 . mat - the matrix
7491 
7492   Level: intermediate
7493 
7494   Notes:
7495   There can be zeros within the blocks
7496 
7497   The blocks can overlap between processes, including laying on more than two processes
7498 
7499 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7500 @*/
7501 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7502 {
7503   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7504   PetscInt          *diag, *odiag, sc;
7505   VecScatter         scatter;
7506   PetscScalar       *seqv;
7507   const PetscScalar *parv;
7508   const PetscInt    *ia, *ja;
7509   PetscBool          set, flag, done;
7510   Mat                AA = mat, A;
7511   MPI_Comm           comm;
7512   PetscMPIInt        rank, size, tag;
7513   MPI_Status         status;
7514   PetscContainer     container;
7515   EnvelopeData      *edata;
7516   Vec                seq, par;
7517   IS                 isglobal;
7518 
7519   PetscFunctionBegin;
7520   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7521   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7522   if (!set || !flag) {
7523     /* TODO: only needs nonzero structure of transpose */
7524     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7525     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7526   }
7527   PetscCall(MatAIJGetLocalMat(AA, &A));
7528   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7529   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7530 
7531   PetscCall(MatGetLocalSize(mat, &n, NULL));
7532   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7533   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7534   PetscCallMPI(MPI_Comm_size(comm, &size));
7535   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7536 
7537   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7538 
7539   if (rank > 0) {
7540     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7541     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7542   }
7543   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7544   for (i = 0; i < n; i++) {
7545     env = PetscMax(env, ja[ia[i + 1] - 1]);
7546     II  = rstart + i;
7547     if (env == II) {
7548       starts[lblocks]  = tbs;
7549       sizes[lblocks++] = 1 + II - tbs;
7550       tbs              = 1 + II;
7551     }
7552   }
7553   if (rank < size - 1) {
7554     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7555     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7556   }
7557 
7558   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7559   if (!set || !flag) PetscCall(MatDestroy(&AA));
7560   PetscCall(MatDestroy(&A));
7561 
7562   PetscCall(PetscNew(&edata));
7563   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7564   edata->n = lblocks;
7565   /* create IS needed for extracting blocks from the original matrix */
7566   PetscCall(PetscMalloc1(lblocks, &edata->is));
7567   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7568 
7569   /* Create the resulting inverse matrix structure with preallocation information */
7570   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7571   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7572   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7573   PetscCall(MatSetType(edata->C, MATAIJ));
7574 
7575   /* Communicate the start and end of each row, from each block to the correct rank */
7576   /* TODO: Use PetscSF instead of VecScatter */
7577   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7578   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7579   PetscCall(VecGetArrayWrite(seq, &seqv));
7580   for (PetscInt i = 0; i < lblocks; i++) {
7581     for (PetscInt j = 0; j < sizes[i]; j++) {
7582       seqv[cnt]     = starts[i];
7583       seqv[cnt + 1] = starts[i] + sizes[i];
7584       cnt += 2;
7585     }
7586   }
7587   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7588   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7589   sc -= cnt;
7590   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7591   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7592   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7593   PetscCall(ISDestroy(&isglobal));
7594   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7595   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7596   PetscCall(VecScatterDestroy(&scatter));
7597   PetscCall(VecDestroy(&seq));
7598   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7599   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7600   PetscCall(VecGetArrayRead(par, &parv));
7601   cnt = 0;
7602   PetscCall(MatGetSize(mat, NULL, &n));
7603   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7604     PetscInt start, end, d = 0, od = 0;
7605 
7606     start = (PetscInt)PetscRealPart(parv[cnt]);
7607     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7608     cnt += 2;
7609 
7610     if (start < cstart) {
7611       od += cstart - start + n - cend;
7612       d += cend - cstart;
7613     } else if (start < cend) {
7614       od += n - cend;
7615       d += cend - start;
7616     } else od += n - start;
7617     if (end <= cstart) {
7618       od -= cstart - end + n - cend;
7619       d -= cend - cstart;
7620     } else if (end < cend) {
7621       od -= n - cend;
7622       d -= cend - end;
7623     } else od -= n - end;
7624 
7625     odiag[i] = od;
7626     diag[i]  = d;
7627   }
7628   PetscCall(VecRestoreArrayRead(par, &parv));
7629   PetscCall(VecDestroy(&par));
7630   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7631   PetscCall(PetscFree2(diag, odiag));
7632   PetscCall(PetscFree2(sizes, starts));
7633 
7634   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7635   PetscCall(PetscContainerSetPointer(container, edata));
7636   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7637   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7638   PetscCall(PetscObjectDereference((PetscObject)container));
7639   PetscFunctionReturn(PETSC_SUCCESS);
7640 }
7641 
7642 /*@
7643   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7644 
7645   Collective
7646 
7647   Input Parameters:
7648 + A     - the matrix
7649 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7650 
7651   Output Parameter:
7652 . C - matrix with inverted block diagonal of `A`
7653 
7654   Level: advanced
7655 
7656   Note:
7657   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7658 
7659 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7660 @*/
7661 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7662 {
7663   PetscContainer   container;
7664   EnvelopeData    *edata;
7665   PetscObjectState nonzerostate;
7666 
7667   PetscFunctionBegin;
7668   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7669   if (!container) {
7670     PetscCall(MatComputeVariableBlockEnvelope(A));
7671     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7672   }
7673   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7674   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7675   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7676   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7677 
7678   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7679   *C = edata->C;
7680 
7681   for (PetscInt i = 0; i < edata->n; i++) {
7682     Mat          D;
7683     PetscScalar *dvalues;
7684 
7685     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7686     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7687     PetscCall(MatSeqDenseInvert(D));
7688     PetscCall(MatDenseGetArray(D, &dvalues));
7689     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7690     PetscCall(MatDestroy(&D));
7691   }
7692   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7693   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7694   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7695   PetscFunctionReturn(PETSC_SUCCESS);
7696 }
7697 
7698 /*@
7699   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7700 
7701   Logically Collective
7702 
7703   Input Parameters:
7704 + mat     - the matrix
7705 . nblocks - the number of blocks on this process, each block can only exist on a single process
7706 - bsizes  - the block sizes
7707 
7708   Level: intermediate
7709 
7710   Notes:
7711   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7712 
7713   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.
7714 
7715 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7716           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7717 @*/
7718 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7719 {
7720   PetscInt i, ncnt = 0, nlocal;
7721 
7722   PetscFunctionBegin;
7723   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7724   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7725   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7726   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7727   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);
7728   PetscCall(PetscFree(mat->bsizes));
7729   mat->nblocks = nblocks;
7730   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7731   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7732   PetscFunctionReturn(PETSC_SUCCESS);
7733 }
7734 
7735 /*@C
7736   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7737 
7738   Logically Collective; No Fortran Support
7739 
7740   Input Parameter:
7741 . mat - the matrix
7742 
7743   Output Parameters:
7744 + nblocks - the number of blocks on this process
7745 - bsizes  - the block sizes
7746 
7747   Level: intermediate
7748 
7749 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7750 @*/
7751 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7752 {
7753   PetscFunctionBegin;
7754   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7755   *nblocks = mat->nblocks;
7756   *bsizes  = mat->bsizes;
7757   PetscFunctionReturn(PETSC_SUCCESS);
7758 }
7759 
7760 /*@
7761   MatSetBlockSizes - Sets the matrix block row and column sizes.
7762 
7763   Logically Collective
7764 
7765   Input Parameters:
7766 + mat - the matrix
7767 . rbs - row block size
7768 - cbs - column block size
7769 
7770   Level: intermediate
7771 
7772   Notes:
7773   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7774   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7775   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7776 
7777   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7778   are compatible with the matrix local sizes.
7779 
7780   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7781 
7782 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7783 @*/
7784 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7785 {
7786   PetscFunctionBegin;
7787   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7788   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7789   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7790   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7791   if (mat->rmap->refcnt) {
7792     ISLocalToGlobalMapping l2g  = NULL;
7793     PetscLayout            nmap = NULL;
7794 
7795     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7796     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7797     PetscCall(PetscLayoutDestroy(&mat->rmap));
7798     mat->rmap          = nmap;
7799     mat->rmap->mapping = l2g;
7800   }
7801   if (mat->cmap->refcnt) {
7802     ISLocalToGlobalMapping l2g  = NULL;
7803     PetscLayout            nmap = NULL;
7804 
7805     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7806     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7807     PetscCall(PetscLayoutDestroy(&mat->cmap));
7808     mat->cmap          = nmap;
7809     mat->cmap->mapping = l2g;
7810   }
7811   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7812   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7813   PetscFunctionReturn(PETSC_SUCCESS);
7814 }
7815 
7816 /*@
7817   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7818 
7819   Logically Collective
7820 
7821   Input Parameters:
7822 + mat     - the matrix
7823 . fromRow - matrix from which to copy row block size
7824 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7825 
7826   Level: developer
7827 
7828 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7829 @*/
7830 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7831 {
7832   PetscFunctionBegin;
7833   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7834   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7835   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7836   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7837   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7838   PetscFunctionReturn(PETSC_SUCCESS);
7839 }
7840 
7841 /*@
7842   MatResidual - Default routine to calculate the residual r = b - Ax
7843 
7844   Collective
7845 
7846   Input Parameters:
7847 + mat - the matrix
7848 . b   - the right-hand-side
7849 - x   - the approximate solution
7850 
7851   Output Parameter:
7852 . r - location to store the residual
7853 
7854   Level: developer
7855 
7856 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7857 @*/
7858 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7859 {
7860   PetscFunctionBegin;
7861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7862   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7863   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7864   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7865   PetscValidType(mat, 1);
7866   MatCheckPreallocated(mat, 1);
7867   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7868   if (!mat->ops->residual) {
7869     PetscCall(MatMult(mat, x, r));
7870     PetscCall(VecAYPX(r, -1.0, b));
7871   } else {
7872     PetscUseTypeMethod(mat, residual, b, x, r);
7873   }
7874   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7875   PetscFunctionReturn(PETSC_SUCCESS);
7876 }
7877 
7878 /*MC
7879     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7880 
7881     Synopsis:
7882     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7883 
7884     Not Collective
7885 
7886     Input Parameters:
7887 +   A - the matrix
7888 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7889 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7890 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7891                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7892                  always used.
7893 
7894     Output Parameters:
7895 +   n - number of local rows in the (possibly compressed) matrix
7896 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7897 .   ja - the column indices
7898 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7899            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7900 
7901     Level: developer
7902 
7903     Note:
7904     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7905 
7906 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7907 M*/
7908 
7909 /*MC
7910     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7911 
7912     Synopsis:
7913     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7914 
7915     Not Collective
7916 
7917     Input Parameters:
7918 +   A - the  matrix
7919 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7920 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7921     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7922                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7923                  always used.
7924 .   n - number of local rows in the (possibly compressed) matrix
7925 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7926 .   ja - the column indices
7927 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7928            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7929 
7930     Level: developer
7931 
7932 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7933 M*/
7934 
7935 /*@C
7936   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7937 
7938   Collective
7939 
7940   Input Parameters:
7941 + mat             - the matrix
7942 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7943 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7944 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7945                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7946                  always used.
7947 
7948   Output Parameters:
7949 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7950 . 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
7951 . ja   - the column indices, use `NULL` if not needed
7952 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7953            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7954 
7955   Level: developer
7956 
7957   Notes:
7958   You CANNOT change any of the ia[] or ja[] values.
7959 
7960   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7961 
7962   Fortran Notes:
7963   Use
7964 .vb
7965     PetscInt, pointer :: ia(:),ja(:)
7966     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7967     ! Access the ith and jth entries via ia(i) and ja(j)
7968 .ve
7969 
7970   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7971 
7972 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7973 @*/
7974 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7975 {
7976   PetscFunctionBegin;
7977   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7978   PetscValidType(mat, 1);
7979   if (n) PetscAssertPointer(n, 5);
7980   if (ia) PetscAssertPointer(ia, 6);
7981   if (ja) PetscAssertPointer(ja, 7);
7982   if (done) PetscAssertPointer(done, 8);
7983   MatCheckPreallocated(mat, 1);
7984   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7985   else {
7986     if (done) *done = PETSC_TRUE;
7987     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7988     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7989     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7990   }
7991   PetscFunctionReturn(PETSC_SUCCESS);
7992 }
7993 
7994 /*@C
7995   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7996 
7997   Collective
7998 
7999   Input Parameters:
8000 + mat             - the matrix
8001 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8002 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8003                 symmetrized
8004 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8005                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8006                  always used.
8007 . n               - number of columns in the (possibly compressed) matrix
8008 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8009 - ja              - the row indices
8010 
8011   Output Parameter:
8012 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8013 
8014   Level: developer
8015 
8016 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8017 @*/
8018 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8019 {
8020   PetscFunctionBegin;
8021   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8022   PetscValidType(mat, 1);
8023   PetscAssertPointer(n, 5);
8024   if (ia) PetscAssertPointer(ia, 6);
8025   if (ja) PetscAssertPointer(ja, 7);
8026   PetscAssertPointer(done, 8);
8027   MatCheckPreallocated(mat, 1);
8028   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8029   else {
8030     *done = PETSC_TRUE;
8031     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8032   }
8033   PetscFunctionReturn(PETSC_SUCCESS);
8034 }
8035 
8036 /*@C
8037   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8038 
8039   Collective
8040 
8041   Input Parameters:
8042 + mat             - the matrix
8043 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8044 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8045 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8046                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8047                  always used.
8048 . n               - size of (possibly compressed) matrix
8049 . ia              - the row pointers
8050 - ja              - the column indices
8051 
8052   Output Parameter:
8053 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8054 
8055   Level: developer
8056 
8057   Note:
8058   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8059   us of the array after it has been restored. If you pass `NULL`, it will
8060   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8061 
8062   Fortran Note:
8063   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8064 
8065 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8066 @*/
8067 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8068 {
8069   PetscFunctionBegin;
8070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8071   PetscValidType(mat, 1);
8072   if (ia) PetscAssertPointer(ia, 6);
8073   if (ja) PetscAssertPointer(ja, 7);
8074   if (done) PetscAssertPointer(done, 8);
8075   MatCheckPreallocated(mat, 1);
8076 
8077   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8078   else {
8079     if (done) *done = PETSC_TRUE;
8080     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8081     if (n) *n = 0;
8082     if (ia) *ia = NULL;
8083     if (ja) *ja = NULL;
8084   }
8085   PetscFunctionReturn(PETSC_SUCCESS);
8086 }
8087 
8088 /*@C
8089   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8090 
8091   Collective
8092 
8093   Input Parameters:
8094 + mat             - the matrix
8095 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8096 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8097 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8098                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8099                  always used.
8100 
8101   Output Parameters:
8102 + n    - size of (possibly compressed) matrix
8103 . ia   - the column pointers
8104 . ja   - the row indices
8105 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8106 
8107   Level: developer
8108 
8109 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8110 @*/
8111 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8112 {
8113   PetscFunctionBegin;
8114   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8115   PetscValidType(mat, 1);
8116   if (ia) PetscAssertPointer(ia, 6);
8117   if (ja) PetscAssertPointer(ja, 7);
8118   PetscAssertPointer(done, 8);
8119   MatCheckPreallocated(mat, 1);
8120 
8121   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8122   else {
8123     *done = PETSC_TRUE;
8124     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8125     if (n) *n = 0;
8126     if (ia) *ia = NULL;
8127     if (ja) *ja = NULL;
8128   }
8129   PetscFunctionReturn(PETSC_SUCCESS);
8130 }
8131 
8132 /*@C
8133   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8134   `MatGetColumnIJ()`.
8135 
8136   Collective
8137 
8138   Input Parameters:
8139 + mat        - the matrix
8140 . ncolors    - maximum color value
8141 . n          - number of entries in colorarray
8142 - colorarray - array indicating color for each column
8143 
8144   Output Parameter:
8145 . iscoloring - coloring generated using colorarray information
8146 
8147   Level: developer
8148 
8149 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8150 @*/
8151 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8152 {
8153   PetscFunctionBegin;
8154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8155   PetscValidType(mat, 1);
8156   PetscAssertPointer(colorarray, 4);
8157   PetscAssertPointer(iscoloring, 5);
8158   MatCheckPreallocated(mat, 1);
8159 
8160   if (!mat->ops->coloringpatch) {
8161     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8162   } else {
8163     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8164   }
8165   PetscFunctionReturn(PETSC_SUCCESS);
8166 }
8167 
8168 /*@
8169   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8170 
8171   Logically Collective
8172 
8173   Input Parameter:
8174 . mat - the factored matrix to be reset
8175 
8176   Level: developer
8177 
8178   Notes:
8179   This routine should be used only with factored matrices formed by in-place
8180   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8181   format).  This option can save memory, for example, when solving nonlinear
8182   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8183   ILU(0) preconditioner.
8184 
8185   One can specify in-place ILU(0) factorization by calling
8186 .vb
8187      PCType(pc,PCILU);
8188      PCFactorSeUseInPlace(pc);
8189 .ve
8190   or by using the options -pc_type ilu -pc_factor_in_place
8191 
8192   In-place factorization ILU(0) can also be used as a local
8193   solver for the blocks within the block Jacobi or additive Schwarz
8194   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8195   for details on setting local solver options.
8196 
8197   Most users should employ the `KSP` interface for linear solvers
8198   instead of working directly with matrix algebra routines such as this.
8199   See, e.g., `KSPCreate()`.
8200 
8201 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8202 @*/
8203 PetscErrorCode MatSetUnfactored(Mat mat)
8204 {
8205   PetscFunctionBegin;
8206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8207   PetscValidType(mat, 1);
8208   MatCheckPreallocated(mat, 1);
8209   mat->factortype = MAT_FACTOR_NONE;
8210   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8211   PetscUseTypeMethod(mat, setunfactored);
8212   PetscFunctionReturn(PETSC_SUCCESS);
8213 }
8214 
8215 /*MC
8216     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8217 
8218     Synopsis:
8219     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8220 
8221     Not Collective
8222 
8223     Input Parameter:
8224 .   x - matrix
8225 
8226     Output Parameters:
8227 +   xx_v - the Fortran pointer to the array
8228 -   ierr - error code
8229 
8230     Example of Usage:
8231 .vb
8232       PetscScalar, pointer xx_v(:,:)
8233       ....
8234       call MatDenseGetArrayF90(x,xx_v,ierr)
8235       a = xx_v(3)
8236       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8237 .ve
8238 
8239     Level: advanced
8240 
8241 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8242 M*/
8243 
8244 /*MC
8245     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8246     accessed with `MatDenseGetArrayF90()`.
8247 
8248     Synopsis:
8249     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8250 
8251     Not Collective
8252 
8253     Input Parameters:
8254 +   x - matrix
8255 -   xx_v - the Fortran90 pointer to the array
8256 
8257     Output Parameter:
8258 .   ierr - error code
8259 
8260     Example of Usage:
8261 .vb
8262        PetscScalar, pointer xx_v(:,:)
8263        ....
8264        call MatDenseGetArrayF90(x,xx_v,ierr)
8265        a = xx_v(3)
8266        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8267 .ve
8268 
8269     Level: advanced
8270 
8271 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8272 M*/
8273 
8274 /*MC
8275     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8276 
8277     Synopsis:
8278     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8279 
8280     Not Collective
8281 
8282     Input Parameter:
8283 .   x - matrix
8284 
8285     Output Parameters:
8286 +   xx_v - the Fortran pointer to the array
8287 -   ierr - error code
8288 
8289     Example of Usage:
8290 .vb
8291       PetscScalar, pointer xx_v(:)
8292       ....
8293       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8294       a = xx_v(3)
8295       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8296 .ve
8297 
8298     Level: advanced
8299 
8300 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8301 M*/
8302 
8303 /*MC
8304     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8305     accessed with `MatSeqAIJGetArrayF90()`.
8306 
8307     Synopsis:
8308     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8309 
8310     Not Collective
8311 
8312     Input Parameters:
8313 +   x - matrix
8314 -   xx_v - the Fortran90 pointer to the array
8315 
8316     Output Parameter:
8317 .   ierr - error code
8318 
8319     Example of Usage:
8320 .vb
8321        PetscScalar, pointer xx_v(:)
8322        ....
8323        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8324        a = xx_v(3)
8325        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8326 .ve
8327 
8328     Level: advanced
8329 
8330 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8331 M*/
8332 
8333 /*@
8334   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8335   as the original matrix.
8336 
8337   Collective
8338 
8339   Input Parameters:
8340 + mat   - the original matrix
8341 . isrow - parallel `IS` containing the rows this processor should obtain
8342 . 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.
8343 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8344 
8345   Output Parameter:
8346 . newmat - the new submatrix, of the same type as the original matrix
8347 
8348   Level: advanced
8349 
8350   Notes:
8351   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8352 
8353   Some matrix types place restrictions on the row and column indices, such
8354   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;
8355   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8356 
8357   The index sets may not have duplicate entries.
8358 
8359   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8360   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8361   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8362   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8363   you are finished using it.
8364 
8365   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8366   the input matrix.
8367 
8368   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8369 
8370   If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature
8371   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8372 
8373   Example usage:
8374   Consider the following 8x8 matrix with 34 non-zero values, that is
8375   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8376   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8377   as follows
8378 .vb
8379             1  2  0  |  0  3  0  |  0  4
8380     Proc0   0  5  6  |  7  0  0  |  8  0
8381             9  0 10  | 11  0  0  | 12  0
8382     -------------------------------------
8383            13  0 14  | 15 16 17  |  0  0
8384     Proc1   0 18  0  | 19 20 21  |  0  0
8385             0  0  0  | 22 23  0  | 24  0
8386     -------------------------------------
8387     Proc2  25 26 27  |  0  0 28  | 29  0
8388            30  0  0  | 31 32 33  |  0 34
8389 .ve
8390 
8391   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8392 
8393 .vb
8394             2  0  |  0  3  0  |  0
8395     Proc0   5  6  |  7  0  0  |  8
8396     -------------------------------
8397     Proc1  18  0  | 19 20 21  |  0
8398     -------------------------------
8399     Proc2  26 27  |  0  0 28  | 29
8400             0  0  | 31 32 33  |  0
8401 .ve
8402 
8403 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8404 @*/
8405 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8406 {
8407   PetscMPIInt size;
8408   Mat        *local;
8409   IS          iscoltmp;
8410   PetscBool   flg;
8411 
8412   PetscFunctionBegin;
8413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8414   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8415   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8416   PetscAssertPointer(newmat, 5);
8417   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8418   PetscValidType(mat, 1);
8419   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8420   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8421 
8422   MatCheckPreallocated(mat, 1);
8423   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8424 
8425   if (!iscol || isrow == iscol) {
8426     PetscBool   stride;
8427     PetscMPIInt grabentirematrix = 0, grab;
8428     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8429     if (stride) {
8430       PetscInt first, step, n, rstart, rend;
8431       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8432       if (step == 1) {
8433         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8434         if (rstart == first) {
8435           PetscCall(ISGetLocalSize(isrow, &n));
8436           if (n == rend - rstart) grabentirematrix = 1;
8437         }
8438       }
8439     }
8440     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8441     if (grab) {
8442       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8443       if (cll == MAT_INITIAL_MATRIX) {
8444         *newmat = mat;
8445         PetscCall(PetscObjectReference((PetscObject)mat));
8446       }
8447       PetscFunctionReturn(PETSC_SUCCESS);
8448     }
8449   }
8450 
8451   if (!iscol) {
8452     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8453   } else {
8454     iscoltmp = iscol;
8455   }
8456 
8457   /* if original matrix is on just one processor then use submatrix generated */
8458   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8459     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8460     goto setproperties;
8461   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8462     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8463     *newmat = *local;
8464     PetscCall(PetscFree(local));
8465     goto setproperties;
8466   } else if (!mat->ops->createsubmatrix) {
8467     /* Create a new matrix type that implements the operation using the full matrix */
8468     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8469     switch (cll) {
8470     case MAT_INITIAL_MATRIX:
8471       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8472       break;
8473     case MAT_REUSE_MATRIX:
8474       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8475       break;
8476     default:
8477       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8478     }
8479     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8480     goto setproperties;
8481   }
8482 
8483   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8484   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8485   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8486 
8487 setproperties:
8488   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8489   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8490   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8491   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8492   PetscFunctionReturn(PETSC_SUCCESS);
8493 }
8494 
8495 /*@
8496   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8497 
8498   Not Collective
8499 
8500   Input Parameters:
8501 + A - the matrix we wish to propagate options from
8502 - B - the matrix we wish to propagate options to
8503 
8504   Level: beginner
8505 
8506   Note:
8507   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8508 
8509 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8510 @*/
8511 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8512 {
8513   PetscFunctionBegin;
8514   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8515   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8516   B->symmetry_eternal            = A->symmetry_eternal;
8517   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8518   B->symmetric                   = A->symmetric;
8519   B->structurally_symmetric      = A->structurally_symmetric;
8520   B->spd                         = A->spd;
8521   B->hermitian                   = A->hermitian;
8522   PetscFunctionReturn(PETSC_SUCCESS);
8523 }
8524 
8525 /*@
8526   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8527   used during the assembly process to store values that belong to
8528   other processors.
8529 
8530   Not Collective
8531 
8532   Input Parameters:
8533 + mat   - the matrix
8534 . size  - the initial size of the stash.
8535 - bsize - the initial size of the block-stash(if used).
8536 
8537   Options Database Keys:
8538 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8539 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8540 
8541   Level: intermediate
8542 
8543   Notes:
8544   The block-stash is used for values set with `MatSetValuesBlocked()` while
8545   the stash is used for values set with `MatSetValues()`
8546 
8547   Run with the option -info and look for output of the form
8548   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8549   to determine the appropriate value, MM, to use for size and
8550   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8551   to determine the value, BMM to use for bsize
8552 
8553 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8554 @*/
8555 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8556 {
8557   PetscFunctionBegin;
8558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8559   PetscValidType(mat, 1);
8560   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8561   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8562   PetscFunctionReturn(PETSC_SUCCESS);
8563 }
8564 
8565 /*@
8566   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8567   the matrix
8568 
8569   Neighbor-wise Collective
8570 
8571   Input Parameters:
8572 + A - the matrix
8573 . x - the vector to be multiplied by the interpolation operator
8574 - y - the vector to be added to the result
8575 
8576   Output Parameter:
8577 . w - the resulting vector
8578 
8579   Level: intermediate
8580 
8581   Notes:
8582   `w` may be the same vector as `y`.
8583 
8584   This allows one to use either the restriction or interpolation (its transpose)
8585   matrix to do the interpolation
8586 
8587 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8588 @*/
8589 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8590 {
8591   PetscInt M, N, Ny;
8592 
8593   PetscFunctionBegin;
8594   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8595   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8596   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8597   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8598   PetscCall(MatGetSize(A, &M, &N));
8599   PetscCall(VecGetSize(y, &Ny));
8600   if (M == Ny) {
8601     PetscCall(MatMultAdd(A, x, y, w));
8602   } else {
8603     PetscCall(MatMultTransposeAdd(A, x, y, w));
8604   }
8605   PetscFunctionReturn(PETSC_SUCCESS);
8606 }
8607 
8608 /*@
8609   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8610   the matrix
8611 
8612   Neighbor-wise Collective
8613 
8614   Input Parameters:
8615 + A - the matrix
8616 - x - the vector to be interpolated
8617 
8618   Output Parameter:
8619 . y - the resulting vector
8620 
8621   Level: intermediate
8622 
8623   Note:
8624   This allows one to use either the restriction or interpolation (its transpose)
8625   matrix to do the interpolation
8626 
8627 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8628 @*/
8629 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8630 {
8631   PetscInt M, N, Ny;
8632 
8633   PetscFunctionBegin;
8634   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8635   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8636   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8637   PetscCall(MatGetSize(A, &M, &N));
8638   PetscCall(VecGetSize(y, &Ny));
8639   if (M == Ny) {
8640     PetscCall(MatMult(A, x, y));
8641   } else {
8642     PetscCall(MatMultTranspose(A, x, y));
8643   }
8644   PetscFunctionReturn(PETSC_SUCCESS);
8645 }
8646 
8647 /*@
8648   MatRestrict - $y = A*x$ or $A^T*x$
8649 
8650   Neighbor-wise Collective
8651 
8652   Input Parameters:
8653 + A - the matrix
8654 - x - the vector to be restricted
8655 
8656   Output Parameter:
8657 . y - the resulting vector
8658 
8659   Level: intermediate
8660 
8661   Note:
8662   This allows one to use either the restriction or interpolation (its transpose)
8663   matrix to do the restriction
8664 
8665 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8666 @*/
8667 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8668 {
8669   PetscInt M, N, Ny;
8670 
8671   PetscFunctionBegin;
8672   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8673   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8674   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8675   PetscCall(MatGetSize(A, &M, &N));
8676   PetscCall(VecGetSize(y, &Ny));
8677   if (M == Ny) {
8678     PetscCall(MatMult(A, x, y));
8679   } else {
8680     PetscCall(MatMultTranspose(A, x, y));
8681   }
8682   PetscFunctionReturn(PETSC_SUCCESS);
8683 }
8684 
8685 /*@
8686   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8687 
8688   Neighbor-wise Collective
8689 
8690   Input Parameters:
8691 + A - the matrix
8692 . x - the input dense matrix to be multiplied
8693 - w - the input dense matrix to be added to the result
8694 
8695   Output Parameter:
8696 . y - the output dense matrix
8697 
8698   Level: intermediate
8699 
8700   Note:
8701   This allows one to use either the restriction or interpolation (its transpose)
8702   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8703   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8704 
8705 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8706 @*/
8707 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8708 {
8709   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8710   PetscBool trans = PETSC_TRUE;
8711   MatReuse  reuse = MAT_INITIAL_MATRIX;
8712 
8713   PetscFunctionBegin;
8714   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8715   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8716   PetscValidType(x, 2);
8717   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8718   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8719   PetscCall(MatGetSize(A, &M, &N));
8720   PetscCall(MatGetSize(x, &Mx, &Nx));
8721   if (N == Mx) trans = PETSC_FALSE;
8722   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);
8723   Mo = trans ? N : M;
8724   if (*y) {
8725     PetscCall(MatGetSize(*y, &My, &Ny));
8726     if (Mo == My && Nx == Ny) {
8727       reuse = MAT_REUSE_MATRIX;
8728     } else {
8729       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);
8730       PetscCall(MatDestroy(y));
8731     }
8732   }
8733 
8734   if (w && *y == w) { /* this is to minimize changes in PCMG */
8735     PetscBool flg;
8736 
8737     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8738     if (w) {
8739       PetscInt My, Ny, Mw, Nw;
8740 
8741       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8742       PetscCall(MatGetSize(*y, &My, &Ny));
8743       PetscCall(MatGetSize(w, &Mw, &Nw));
8744       if (!flg || My != Mw || Ny != Nw) w = NULL;
8745     }
8746     if (!w) {
8747       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8748       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8749       PetscCall(PetscObjectDereference((PetscObject)w));
8750     } else {
8751       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8752     }
8753   }
8754   if (!trans) {
8755     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8756   } else {
8757     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8758   }
8759   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8760   PetscFunctionReturn(PETSC_SUCCESS);
8761 }
8762 
8763 /*@
8764   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8765 
8766   Neighbor-wise Collective
8767 
8768   Input Parameters:
8769 + A - the matrix
8770 - x - the input dense matrix
8771 
8772   Output Parameter:
8773 . y - the output dense matrix
8774 
8775   Level: intermediate
8776 
8777   Note:
8778   This allows one to use either the restriction or interpolation (its transpose)
8779   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8780   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8781 
8782 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8783 @*/
8784 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8785 {
8786   PetscFunctionBegin;
8787   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8788   PetscFunctionReturn(PETSC_SUCCESS);
8789 }
8790 
8791 /*@
8792   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8793 
8794   Neighbor-wise Collective
8795 
8796   Input Parameters:
8797 + A - the matrix
8798 - x - the input dense matrix
8799 
8800   Output Parameter:
8801 . y - the output dense matrix
8802 
8803   Level: intermediate
8804 
8805   Note:
8806   This allows one to use either the restriction or interpolation (its transpose)
8807   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8808   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8809 
8810 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8811 @*/
8812 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8813 {
8814   PetscFunctionBegin;
8815   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8816   PetscFunctionReturn(PETSC_SUCCESS);
8817 }
8818 
8819 /*@
8820   MatGetNullSpace - retrieves the null space of a matrix.
8821 
8822   Logically Collective
8823 
8824   Input Parameters:
8825 + mat    - the matrix
8826 - nullsp - the null space object
8827 
8828   Level: developer
8829 
8830 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8831 @*/
8832 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8833 {
8834   PetscFunctionBegin;
8835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8836   PetscAssertPointer(nullsp, 2);
8837   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8838   PetscFunctionReturn(PETSC_SUCCESS);
8839 }
8840 
8841 /*@
8842   MatSetNullSpace - attaches a null space to a matrix.
8843 
8844   Logically Collective
8845 
8846   Input Parameters:
8847 + mat    - the matrix
8848 - nullsp - the null space object
8849 
8850   Level: advanced
8851 
8852   Notes:
8853   This null space is used by the `KSP` linear solvers to solve singular systems.
8854 
8855   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`
8856 
8857   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
8858   to zero but the linear system will still be solved in a least squares sense.
8859 
8860   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8861   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)$.
8862   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
8863   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
8864   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$).
8865   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8866 
8867   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8868   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8869   routine also automatically calls `MatSetTransposeNullSpace()`.
8870 
8871   The user should call `MatNullSpaceDestroy()`.
8872 
8873 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8874           `KSPSetPCSide()`
8875 @*/
8876 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8877 {
8878   PetscFunctionBegin;
8879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8880   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8881   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8882   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8883   mat->nullsp = nullsp;
8884   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8885   PetscFunctionReturn(PETSC_SUCCESS);
8886 }
8887 
8888 /*@
8889   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8890 
8891   Logically Collective
8892 
8893   Input Parameters:
8894 + mat    - the matrix
8895 - nullsp - the null space object
8896 
8897   Level: developer
8898 
8899 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8900 @*/
8901 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8902 {
8903   PetscFunctionBegin;
8904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8905   PetscValidType(mat, 1);
8906   PetscAssertPointer(nullsp, 2);
8907   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8908   PetscFunctionReturn(PETSC_SUCCESS);
8909 }
8910 
8911 /*@
8912   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8913 
8914   Logically Collective
8915 
8916   Input Parameters:
8917 + mat    - the matrix
8918 - nullsp - the null space object
8919 
8920   Level: advanced
8921 
8922   Notes:
8923   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8924 
8925   See `MatSetNullSpace()`
8926 
8927 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8928 @*/
8929 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8930 {
8931   PetscFunctionBegin;
8932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8933   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8934   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8935   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8936   mat->transnullsp = nullsp;
8937   PetscFunctionReturn(PETSC_SUCCESS);
8938 }
8939 
8940 /*@
8941   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8942   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8943 
8944   Logically Collective
8945 
8946   Input Parameters:
8947 + mat    - the matrix
8948 - nullsp - the null space object
8949 
8950   Level: advanced
8951 
8952   Notes:
8953   Overwrites any previous near null space that may have been attached
8954 
8955   You can remove the null space by calling this routine with an `nullsp` of `NULL`
8956 
8957 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8958 @*/
8959 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8960 {
8961   PetscFunctionBegin;
8962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8963   PetscValidType(mat, 1);
8964   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8965   MatCheckPreallocated(mat, 1);
8966   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8967   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8968   mat->nearnullsp = nullsp;
8969   PetscFunctionReturn(PETSC_SUCCESS);
8970 }
8971 
8972 /*@
8973   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8974 
8975   Not Collective
8976 
8977   Input Parameter:
8978 . mat - the matrix
8979 
8980   Output Parameter:
8981 . nullsp - the null space object, `NULL` if not set
8982 
8983   Level: advanced
8984 
8985 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8986 @*/
8987 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8988 {
8989   PetscFunctionBegin;
8990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8991   PetscValidType(mat, 1);
8992   PetscAssertPointer(nullsp, 2);
8993   MatCheckPreallocated(mat, 1);
8994   *nullsp = mat->nearnullsp;
8995   PetscFunctionReturn(PETSC_SUCCESS);
8996 }
8997 
8998 /*@C
8999   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9000 
9001   Collective
9002 
9003   Input Parameters:
9004 + mat  - the matrix
9005 . row  - row/column permutation
9006 - info - information on desired factorization process
9007 
9008   Level: developer
9009 
9010   Notes:
9011   Probably really in-place only when level of fill is zero, otherwise allocates
9012   new space to store factored matrix and deletes previous memory.
9013 
9014   Most users should employ the `KSP` interface for linear solvers
9015   instead of working directly with matrix algebra routines such as this.
9016   See, e.g., `KSPCreate()`.
9017 
9018   Developer Note:
9019   The Fortran interface is not autogenerated as the
9020   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9021 
9022 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9023 @*/
9024 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9025 {
9026   PetscFunctionBegin;
9027   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9028   PetscValidType(mat, 1);
9029   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9030   PetscAssertPointer(info, 3);
9031   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9032   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9033   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9034   MatCheckPreallocated(mat, 1);
9035   PetscUseTypeMethod(mat, iccfactor, row, info);
9036   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9037   PetscFunctionReturn(PETSC_SUCCESS);
9038 }
9039 
9040 /*@
9041   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9042   ghosted ones.
9043 
9044   Not Collective
9045 
9046   Input Parameters:
9047 + mat  - the matrix
9048 - diag - the diagonal values, including ghost ones
9049 
9050   Level: developer
9051 
9052   Notes:
9053   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9054 
9055   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9056 
9057 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9058 @*/
9059 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9060 {
9061   PetscMPIInt size;
9062 
9063   PetscFunctionBegin;
9064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9065   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9066   PetscValidType(mat, 1);
9067 
9068   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9069   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9070   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9071   if (size == 1) {
9072     PetscInt n, m;
9073     PetscCall(VecGetSize(diag, &n));
9074     PetscCall(MatGetSize(mat, NULL, &m));
9075     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9076     PetscCall(MatDiagonalScale(mat, NULL, diag));
9077   } else {
9078     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9079   }
9080   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9081   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9082   PetscFunctionReturn(PETSC_SUCCESS);
9083 }
9084 
9085 /*@
9086   MatGetInertia - Gets the inertia from a factored matrix
9087 
9088   Collective
9089 
9090   Input Parameter:
9091 . mat - the matrix
9092 
9093   Output Parameters:
9094 + nneg  - number of negative eigenvalues
9095 . nzero - number of zero eigenvalues
9096 - npos  - number of positive eigenvalues
9097 
9098   Level: advanced
9099 
9100   Note:
9101   Matrix must have been factored by `MatCholeskyFactor()`
9102 
9103 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9104 @*/
9105 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9106 {
9107   PetscFunctionBegin;
9108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9109   PetscValidType(mat, 1);
9110   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9112   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9113   PetscFunctionReturn(PETSC_SUCCESS);
9114 }
9115 
9116 /*@C
9117   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9118 
9119   Neighbor-wise Collective
9120 
9121   Input Parameters:
9122 + mat - the factored matrix obtained with `MatGetFactor()`
9123 - b   - the right-hand-side vectors
9124 
9125   Output Parameter:
9126 . x - the result vectors
9127 
9128   Level: developer
9129 
9130   Note:
9131   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9132   call `MatSolves`(A,x,x).
9133 
9134 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9135 @*/
9136 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9137 {
9138   PetscFunctionBegin;
9139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9140   PetscValidType(mat, 1);
9141   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9142   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9143   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9144 
9145   MatCheckPreallocated(mat, 1);
9146   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9147   PetscUseTypeMethod(mat, solves, b, x);
9148   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9149   PetscFunctionReturn(PETSC_SUCCESS);
9150 }
9151 
9152 /*@
9153   MatIsSymmetric - Test whether a matrix is symmetric
9154 
9155   Collective
9156 
9157   Input Parameters:
9158 + A   - the matrix to test
9159 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9160 
9161   Output Parameter:
9162 . flg - the result
9163 
9164   Level: intermediate
9165 
9166   Notes:
9167   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9168 
9169   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9170 
9171   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9172   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9173 
9174 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9175           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9176 @*/
9177 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9178 {
9179   PetscFunctionBegin;
9180   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9181   PetscAssertPointer(flg, 3);
9182 
9183   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9184   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9185   else {
9186     PetscUseTypeMethod(A, issymmetric, tol, flg);
9187     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9188   }
9189   PetscFunctionReturn(PETSC_SUCCESS);
9190 }
9191 
9192 /*@
9193   MatIsHermitian - Test whether a matrix is Hermitian
9194 
9195   Collective
9196 
9197   Input Parameters:
9198 + A   - the matrix to test
9199 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9200 
9201   Output Parameter:
9202 . flg - the result
9203 
9204   Level: intermediate
9205 
9206   Notes:
9207   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9208 
9209   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9210 
9211   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9212   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9213 
9214 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9215           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9216 @*/
9217 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9218 {
9219   PetscFunctionBegin;
9220   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9221   PetscAssertPointer(flg, 3);
9222 
9223   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9224   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9225   else {
9226     PetscUseTypeMethod(A, ishermitian, tol, flg);
9227     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9228   }
9229   PetscFunctionReturn(PETSC_SUCCESS);
9230 }
9231 
9232 /*@
9233   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9234 
9235   Not Collective
9236 
9237   Input Parameter:
9238 . A - the matrix to check
9239 
9240   Output Parameters:
9241 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9242 - flg - the result (only valid if set is `PETSC_TRUE`)
9243 
9244   Level: advanced
9245 
9246   Notes:
9247   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9248   if you want it explicitly checked
9249 
9250   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9251   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9252 
9253 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9254 @*/
9255 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9256 {
9257   PetscFunctionBegin;
9258   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9259   PetscAssertPointer(set, 2);
9260   PetscAssertPointer(flg, 3);
9261   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9262     *set = PETSC_TRUE;
9263     *flg = PetscBool3ToBool(A->symmetric);
9264   } else {
9265     *set = PETSC_FALSE;
9266   }
9267   PetscFunctionReturn(PETSC_SUCCESS);
9268 }
9269 
9270 /*@
9271   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9272 
9273   Not Collective
9274 
9275   Input Parameter:
9276 . A - the matrix to check
9277 
9278   Output Parameters:
9279 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9280 - flg - the result (only valid if set is `PETSC_TRUE`)
9281 
9282   Level: advanced
9283 
9284   Notes:
9285   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9286 
9287   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9288   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9289 
9290 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9291 @*/
9292 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9293 {
9294   PetscFunctionBegin;
9295   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9296   PetscAssertPointer(set, 2);
9297   PetscAssertPointer(flg, 3);
9298   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9299     *set = PETSC_TRUE;
9300     *flg = PetscBool3ToBool(A->spd);
9301   } else {
9302     *set = PETSC_FALSE;
9303   }
9304   PetscFunctionReturn(PETSC_SUCCESS);
9305 }
9306 
9307 /*@
9308   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9309 
9310   Not Collective
9311 
9312   Input Parameter:
9313 . A - the matrix to check
9314 
9315   Output Parameters:
9316 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9317 - flg - the result (only valid if set is `PETSC_TRUE`)
9318 
9319   Level: advanced
9320 
9321   Notes:
9322   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9323   if you want it explicitly checked
9324 
9325   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9326   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9327 
9328 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9329 @*/
9330 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9331 {
9332   PetscFunctionBegin;
9333   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9334   PetscAssertPointer(set, 2);
9335   PetscAssertPointer(flg, 3);
9336   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9337     *set = PETSC_TRUE;
9338     *flg = PetscBool3ToBool(A->hermitian);
9339   } else {
9340     *set = PETSC_FALSE;
9341   }
9342   PetscFunctionReturn(PETSC_SUCCESS);
9343 }
9344 
9345 /*@
9346   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9347 
9348   Collective
9349 
9350   Input Parameter:
9351 . A - the matrix to test
9352 
9353   Output Parameter:
9354 . flg - the result
9355 
9356   Level: intermediate
9357 
9358   Notes:
9359   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9360 
9361   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
9362   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9363 
9364 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9365 @*/
9366 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9367 {
9368   PetscFunctionBegin;
9369   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9370   PetscAssertPointer(flg, 2);
9371   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9372     *flg = PetscBool3ToBool(A->structurally_symmetric);
9373   } else {
9374     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9375     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9376   }
9377   PetscFunctionReturn(PETSC_SUCCESS);
9378 }
9379 
9380 /*@
9381   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9382 
9383   Not Collective
9384 
9385   Input Parameter:
9386 . A - the matrix to check
9387 
9388   Output Parameters:
9389 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9390 - flg - the result (only valid if set is PETSC_TRUE)
9391 
9392   Level: advanced
9393 
9394   Notes:
9395   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
9396   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9397 
9398   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9399 
9400 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9401 @*/
9402 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9403 {
9404   PetscFunctionBegin;
9405   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9406   PetscAssertPointer(set, 2);
9407   PetscAssertPointer(flg, 3);
9408   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9409     *set = PETSC_TRUE;
9410     *flg = PetscBool3ToBool(A->structurally_symmetric);
9411   } else {
9412     *set = PETSC_FALSE;
9413   }
9414   PetscFunctionReturn(PETSC_SUCCESS);
9415 }
9416 
9417 /*@
9418   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9419   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9420 
9421   Not Collective
9422 
9423   Input Parameter:
9424 . mat - the matrix
9425 
9426   Output Parameters:
9427 + nstash    - the size of the stash
9428 . reallocs  - the number of additional mallocs incurred.
9429 . bnstash   - the size of the block stash
9430 - breallocs - the number of additional mallocs incurred.in the block stash
9431 
9432   Level: advanced
9433 
9434 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9435 @*/
9436 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9437 {
9438   PetscFunctionBegin;
9439   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9440   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9441   PetscFunctionReturn(PETSC_SUCCESS);
9442 }
9443 
9444 /*@C
9445   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9446   parallel layout, `PetscLayout` for rows and columns
9447 
9448   Collective
9449 
9450   Input Parameter:
9451 . mat - the matrix
9452 
9453   Output Parameters:
9454 + right - (optional) vector that the matrix can be multiplied against
9455 - left  - (optional) vector that the matrix vector product can be stored in
9456 
9457   Level: advanced
9458 
9459   Notes:
9460   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()`.
9461 
9462   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9463 
9464 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9465 @*/
9466 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9467 {
9468   PetscFunctionBegin;
9469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9470   PetscValidType(mat, 1);
9471   if (mat->ops->getvecs) {
9472     PetscUseTypeMethod(mat, getvecs, right, left);
9473   } else {
9474     if (right) {
9475       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9476       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9477       PetscCall(VecSetType(*right, mat->defaultvectype));
9478 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9479       if (mat->boundtocpu && mat->bindingpropagates) {
9480         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9481         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9482       }
9483 #endif
9484     }
9485     if (left) {
9486       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9487       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9488       PetscCall(VecSetType(*left, mat->defaultvectype));
9489 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9490       if (mat->boundtocpu && mat->bindingpropagates) {
9491         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9492         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9493       }
9494 #endif
9495     }
9496   }
9497   PetscFunctionReturn(PETSC_SUCCESS);
9498 }
9499 
9500 /*@C
9501   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9502   with default values.
9503 
9504   Not Collective
9505 
9506   Input Parameter:
9507 . info - the `MatFactorInfo` data structure
9508 
9509   Level: developer
9510 
9511   Notes:
9512   The solvers are generally used through the `KSP` and `PC` objects, for example
9513   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9514 
9515   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9516 
9517   Developer Note:
9518   The Fortran interface is not autogenerated as the
9519   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9520 
9521 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9522 @*/
9523 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9524 {
9525   PetscFunctionBegin;
9526   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9527   PetscFunctionReturn(PETSC_SUCCESS);
9528 }
9529 
9530 /*@
9531   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9532 
9533   Collective
9534 
9535   Input Parameters:
9536 + mat - the factored matrix
9537 - is  - the index set defining the Schur indices (0-based)
9538 
9539   Level: advanced
9540 
9541   Notes:
9542   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9543 
9544   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9545 
9546   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9547 
9548 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9549           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9550 @*/
9551 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9552 {
9553   PetscErrorCode (*f)(Mat, IS);
9554 
9555   PetscFunctionBegin;
9556   PetscValidType(mat, 1);
9557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9558   PetscValidType(is, 2);
9559   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9560   PetscCheckSameComm(mat, 1, is, 2);
9561   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9562   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9563   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9564   PetscCall(MatDestroy(&mat->schur));
9565   PetscCall((*f)(mat, is));
9566   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9567   PetscFunctionReturn(PETSC_SUCCESS);
9568 }
9569 
9570 /*@
9571   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9572 
9573   Logically Collective
9574 
9575   Input Parameters:
9576 + F      - the factored matrix obtained by calling `MatGetFactor()`
9577 . S      - location where to return the Schur complement, can be `NULL`
9578 - status - the status of the Schur complement matrix, can be `NULL`
9579 
9580   Level: advanced
9581 
9582   Notes:
9583   You must call `MatFactorSetSchurIS()` before calling this routine.
9584 
9585   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9586 
9587   The routine provides a copy of the Schur matrix stored within the solver data structures.
9588   The caller must destroy the object when it is no longer needed.
9589   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9590 
9591   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)
9592 
9593   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9594 
9595   Developer Note:
9596   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9597   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9598 
9599 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9600 @*/
9601 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9602 {
9603   PetscFunctionBegin;
9604   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9605   if (S) PetscAssertPointer(S, 2);
9606   if (status) PetscAssertPointer(status, 3);
9607   if (S) {
9608     PetscErrorCode (*f)(Mat, Mat *);
9609 
9610     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9611     if (f) {
9612       PetscCall((*f)(F, S));
9613     } else {
9614       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9615     }
9616   }
9617   if (status) *status = F->schur_status;
9618   PetscFunctionReturn(PETSC_SUCCESS);
9619 }
9620 
9621 /*@
9622   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9623 
9624   Logically Collective
9625 
9626   Input Parameters:
9627 + F      - the factored matrix obtained by calling `MatGetFactor()`
9628 . S      - location where to return the Schur complement, can be `NULL`
9629 - status - the status of the Schur complement matrix, can be `NULL`
9630 
9631   Level: advanced
9632 
9633   Notes:
9634   You must call `MatFactorSetSchurIS()` before calling this routine.
9635 
9636   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9637 
9638   The routine returns a the Schur Complement stored within the data structures of the solver.
9639 
9640   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9641 
9642   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9643 
9644   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9645 
9646   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9647 
9648 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9649 @*/
9650 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9651 {
9652   PetscFunctionBegin;
9653   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9654   if (S) {
9655     PetscAssertPointer(S, 2);
9656     *S = F->schur;
9657   }
9658   if (status) {
9659     PetscAssertPointer(status, 3);
9660     *status = F->schur_status;
9661   }
9662   PetscFunctionReturn(PETSC_SUCCESS);
9663 }
9664 
9665 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9666 {
9667   Mat S = F->schur;
9668 
9669   PetscFunctionBegin;
9670   switch (F->schur_status) {
9671   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9672   case MAT_FACTOR_SCHUR_INVERTED:
9673     if (S) {
9674       S->ops->solve             = NULL;
9675       S->ops->matsolve          = NULL;
9676       S->ops->solvetranspose    = NULL;
9677       S->ops->matsolvetranspose = NULL;
9678       S->ops->solveadd          = NULL;
9679       S->ops->solvetransposeadd = NULL;
9680       S->factortype             = MAT_FACTOR_NONE;
9681       PetscCall(PetscFree(S->solvertype));
9682     }
9683   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9684     break;
9685   default:
9686     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9687   }
9688   PetscFunctionReturn(PETSC_SUCCESS);
9689 }
9690 
9691 /*@
9692   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9693 
9694   Logically Collective
9695 
9696   Input Parameters:
9697 + F      - the factored matrix obtained by calling `MatGetFactor()`
9698 . S      - location where the Schur complement is stored
9699 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9700 
9701   Level: advanced
9702 
9703 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9704 @*/
9705 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9706 {
9707   PetscFunctionBegin;
9708   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9709   if (S) {
9710     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9711     *S = NULL;
9712   }
9713   F->schur_status = status;
9714   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9715   PetscFunctionReturn(PETSC_SUCCESS);
9716 }
9717 
9718 /*@
9719   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9720 
9721   Logically Collective
9722 
9723   Input Parameters:
9724 + F   - the factored matrix obtained by calling `MatGetFactor()`
9725 . rhs - location where the right hand side of the Schur complement system is stored
9726 - sol - location where the solution of the Schur complement system has to be returned
9727 
9728   Level: advanced
9729 
9730   Notes:
9731   The sizes of the vectors should match the size of the Schur complement
9732 
9733   Must be called after `MatFactorSetSchurIS()`
9734 
9735 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9736 @*/
9737 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9738 {
9739   PetscFunctionBegin;
9740   PetscValidType(F, 1);
9741   PetscValidType(rhs, 2);
9742   PetscValidType(sol, 3);
9743   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9744   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9745   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9746   PetscCheckSameComm(F, 1, rhs, 2);
9747   PetscCheckSameComm(F, 1, sol, 3);
9748   PetscCall(MatFactorFactorizeSchurComplement(F));
9749   switch (F->schur_status) {
9750   case MAT_FACTOR_SCHUR_FACTORED:
9751     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9752     break;
9753   case MAT_FACTOR_SCHUR_INVERTED:
9754     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9755     break;
9756   default:
9757     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9758   }
9759   PetscFunctionReturn(PETSC_SUCCESS);
9760 }
9761 
9762 /*@
9763   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9764 
9765   Logically Collective
9766 
9767   Input Parameters:
9768 + F   - the factored matrix obtained by calling `MatGetFactor()`
9769 . rhs - location where the right hand side of the Schur complement system is stored
9770 - sol - location where the solution of the Schur complement system has to be returned
9771 
9772   Level: advanced
9773 
9774   Notes:
9775   The sizes of the vectors should match the size of the Schur complement
9776 
9777   Must be called after `MatFactorSetSchurIS()`
9778 
9779 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9780 @*/
9781 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9782 {
9783   PetscFunctionBegin;
9784   PetscValidType(F, 1);
9785   PetscValidType(rhs, 2);
9786   PetscValidType(sol, 3);
9787   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9788   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9789   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9790   PetscCheckSameComm(F, 1, rhs, 2);
9791   PetscCheckSameComm(F, 1, sol, 3);
9792   PetscCall(MatFactorFactorizeSchurComplement(F));
9793   switch (F->schur_status) {
9794   case MAT_FACTOR_SCHUR_FACTORED:
9795     PetscCall(MatSolve(F->schur, rhs, sol));
9796     break;
9797   case MAT_FACTOR_SCHUR_INVERTED:
9798     PetscCall(MatMult(F->schur, rhs, sol));
9799     break;
9800   default:
9801     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9802   }
9803   PetscFunctionReturn(PETSC_SUCCESS);
9804 }
9805 
9806 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9807 #if PetscDefined(HAVE_CUDA)
9808 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9809 #endif
9810 
9811 /* Schur status updated in the interface */
9812 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9813 {
9814   Mat S = F->schur;
9815 
9816   PetscFunctionBegin;
9817   if (S) {
9818     PetscMPIInt size;
9819     PetscBool   isdense, isdensecuda;
9820 
9821     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9822     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9823     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9824     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9825     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9826     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9827     if (isdense) {
9828       PetscCall(MatSeqDenseInvertFactors_Private(S));
9829     } else if (isdensecuda) {
9830 #if defined(PETSC_HAVE_CUDA)
9831       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9832 #endif
9833     }
9834     // HIP??????????????
9835     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9836   }
9837   PetscFunctionReturn(PETSC_SUCCESS);
9838 }
9839 
9840 /*@
9841   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9842 
9843   Logically Collective
9844 
9845   Input Parameter:
9846 . F - the factored matrix obtained by calling `MatGetFactor()`
9847 
9848   Level: advanced
9849 
9850   Notes:
9851   Must be called after `MatFactorSetSchurIS()`.
9852 
9853   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9854 
9855 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9856 @*/
9857 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9858 {
9859   PetscFunctionBegin;
9860   PetscValidType(F, 1);
9861   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9862   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9863   PetscCall(MatFactorFactorizeSchurComplement(F));
9864   PetscCall(MatFactorInvertSchurComplement_Private(F));
9865   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9866   PetscFunctionReturn(PETSC_SUCCESS);
9867 }
9868 
9869 /*@
9870   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9871 
9872   Logically Collective
9873 
9874   Input Parameter:
9875 . F - the factored matrix obtained by calling `MatGetFactor()`
9876 
9877   Level: advanced
9878 
9879   Note:
9880   Must be called after `MatFactorSetSchurIS()`
9881 
9882 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9883 @*/
9884 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9885 {
9886   MatFactorInfo info;
9887 
9888   PetscFunctionBegin;
9889   PetscValidType(F, 1);
9890   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9891   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9892   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9893   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9894   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9895     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9896   } else {
9897     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9898   }
9899   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9900   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9901   PetscFunctionReturn(PETSC_SUCCESS);
9902 }
9903 
9904 /*@
9905   MatPtAP - Creates the matrix product $C = P^T * A * P$
9906 
9907   Neighbor-wise Collective
9908 
9909   Input Parameters:
9910 + A     - the matrix
9911 . P     - the projection matrix
9912 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9913 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9914           if the result is a dense matrix this is irrelevant
9915 
9916   Output Parameter:
9917 . C - the product matrix
9918 
9919   Level: intermediate
9920 
9921   Notes:
9922   C will be created and must be destroyed by the user with `MatDestroy()`.
9923 
9924   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9925 
9926   Developer Note:
9927   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9928 
9929 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9930 @*/
9931 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9932 {
9933   PetscFunctionBegin;
9934   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9935   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9936 
9937   if (scall == MAT_INITIAL_MATRIX) {
9938     PetscCall(MatProductCreate(A, P, NULL, C));
9939     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9940     PetscCall(MatProductSetAlgorithm(*C, "default"));
9941     PetscCall(MatProductSetFill(*C, fill));
9942 
9943     (*C)->product->api_user = PETSC_TRUE;
9944     PetscCall(MatProductSetFromOptions(*C));
9945     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);
9946     PetscCall(MatProductSymbolic(*C));
9947   } else { /* scall == MAT_REUSE_MATRIX */
9948     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9949   }
9950 
9951   PetscCall(MatProductNumeric(*C));
9952   (*C)->symmetric = A->symmetric;
9953   (*C)->spd       = A->spd;
9954   PetscFunctionReturn(PETSC_SUCCESS);
9955 }
9956 
9957 /*@
9958   MatRARt - Creates the matrix product $C = R * A * R^T$
9959 
9960   Neighbor-wise Collective
9961 
9962   Input Parameters:
9963 + A     - the matrix
9964 . R     - the projection matrix
9965 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9966 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9967           if the result is a dense matrix this is irrelevant
9968 
9969   Output Parameter:
9970 . C - the product matrix
9971 
9972   Level: intermediate
9973 
9974   Notes:
9975   C will be created and must be destroyed by the user with `MatDestroy()`.
9976 
9977   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9978 
9979   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9980   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9981   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9982   We recommend using MatPtAP().
9983 
9984 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9985 @*/
9986 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9987 {
9988   PetscFunctionBegin;
9989   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9990   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9991 
9992   if (scall == MAT_INITIAL_MATRIX) {
9993     PetscCall(MatProductCreate(A, R, NULL, C));
9994     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9995     PetscCall(MatProductSetAlgorithm(*C, "default"));
9996     PetscCall(MatProductSetFill(*C, fill));
9997 
9998     (*C)->product->api_user = PETSC_TRUE;
9999     PetscCall(MatProductSetFromOptions(*C));
10000     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);
10001     PetscCall(MatProductSymbolic(*C));
10002   } else { /* scall == MAT_REUSE_MATRIX */
10003     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10004   }
10005 
10006   PetscCall(MatProductNumeric(*C));
10007   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10008   PetscFunctionReturn(PETSC_SUCCESS);
10009 }
10010 
10011 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10012 {
10013   PetscFunctionBegin;
10014   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10015 
10016   if (scall == MAT_INITIAL_MATRIX) {
10017     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10018     PetscCall(MatProductCreate(A, B, NULL, C));
10019     PetscCall(MatProductSetType(*C, ptype));
10020     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10021     PetscCall(MatProductSetFill(*C, fill));
10022 
10023     (*C)->product->api_user = PETSC_TRUE;
10024     PetscCall(MatProductSetFromOptions(*C));
10025     PetscCall(MatProductSymbolic(*C));
10026   } else { /* scall == MAT_REUSE_MATRIX */
10027     Mat_Product *product = (*C)->product;
10028     PetscBool    isdense;
10029 
10030     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10031     if (isdense && product && product->type != ptype) {
10032       PetscCall(MatProductClear(*C));
10033       product = NULL;
10034     }
10035     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10036     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10037       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10038       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10039       product           = (*C)->product;
10040       product->fill     = fill;
10041       product->api_user = PETSC_TRUE;
10042       product->clear    = PETSC_TRUE;
10043 
10044       PetscCall(MatProductSetType(*C, ptype));
10045       PetscCall(MatProductSetFromOptions(*C));
10046       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);
10047       PetscCall(MatProductSymbolic(*C));
10048     } else { /* user may change input matrices A or B when REUSE */
10049       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10050     }
10051   }
10052   PetscCall(MatProductNumeric(*C));
10053   PetscFunctionReturn(PETSC_SUCCESS);
10054 }
10055 
10056 /*@
10057   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10058 
10059   Neighbor-wise Collective
10060 
10061   Input Parameters:
10062 + A     - the left matrix
10063 . B     - the right matrix
10064 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10065 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10066           if the result is a dense matrix this is irrelevant
10067 
10068   Output Parameter:
10069 . C - the product matrix
10070 
10071   Notes:
10072   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10073 
10074   `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
10075   call to this function with `MAT_INITIAL_MATRIX`.
10076 
10077   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10078 
10079   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`,
10080   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10081 
10082   Example of Usage:
10083 .vb
10084      MatProductCreate(A,B,NULL,&C);
10085      MatProductSetType(C,MATPRODUCT_AB);
10086      MatProductSymbolic(C);
10087      MatProductNumeric(C); // compute C=A * B
10088      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10089      MatProductNumeric(C);
10090      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10091      MatProductNumeric(C);
10092 .ve
10093 
10094   Level: intermediate
10095 
10096 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10097 @*/
10098 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10099 {
10100   PetscFunctionBegin;
10101   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10102   PetscFunctionReturn(PETSC_SUCCESS);
10103 }
10104 
10105 /*@
10106   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10107 
10108   Neighbor-wise Collective
10109 
10110   Input Parameters:
10111 + A     - the left matrix
10112 . B     - the right matrix
10113 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10114 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10115 
10116   Output Parameter:
10117 . C - the product matrix
10118 
10119   Options Database Key:
10120 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10121               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10122               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10123 
10124   Level: intermediate
10125 
10126   Notes:
10127   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10128 
10129   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10130 
10131   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10132   actually needed.
10133 
10134   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10135   and for pairs of `MATMPIDENSE` matrices.
10136 
10137   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10138 
10139 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10140 @*/
10141 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10142 {
10143   PetscFunctionBegin;
10144   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10145   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10146   PetscFunctionReturn(PETSC_SUCCESS);
10147 }
10148 
10149 /*@
10150   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10151 
10152   Neighbor-wise Collective
10153 
10154   Input Parameters:
10155 + A     - the left matrix
10156 . B     - the right matrix
10157 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10158 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10159 
10160   Output Parameter:
10161 . C - the product matrix
10162 
10163   Level: intermediate
10164 
10165   Notes:
10166   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10167 
10168   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10169 
10170   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10171 
10172   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10173   actually needed.
10174 
10175   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10176   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10177 
10178 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10179 @*/
10180 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10181 {
10182   PetscFunctionBegin;
10183   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10184   PetscFunctionReturn(PETSC_SUCCESS);
10185 }
10186 
10187 /*@
10188   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10189 
10190   Neighbor-wise Collective
10191 
10192   Input Parameters:
10193 + A     - the left matrix
10194 . B     - the middle matrix
10195 . C     - the right matrix
10196 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10197 - 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
10198           if the result is a dense matrix this is irrelevant
10199 
10200   Output Parameter:
10201 . D - the product matrix
10202 
10203   Level: intermediate
10204 
10205   Notes:
10206   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10207 
10208   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10209 
10210   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10211 
10212   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10213   actually needed.
10214 
10215   If you have many matrices with the same non-zero structure to multiply, you
10216   should use `MAT_REUSE_MATRIX` in all calls but the first
10217 
10218 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10219 @*/
10220 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10221 {
10222   PetscFunctionBegin;
10223   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10224   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10225 
10226   if (scall == MAT_INITIAL_MATRIX) {
10227     PetscCall(MatProductCreate(A, B, C, D));
10228     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10229     PetscCall(MatProductSetAlgorithm(*D, "default"));
10230     PetscCall(MatProductSetFill(*D, fill));
10231 
10232     (*D)->product->api_user = PETSC_TRUE;
10233     PetscCall(MatProductSetFromOptions(*D));
10234     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,
10235                ((PetscObject)C)->type_name);
10236     PetscCall(MatProductSymbolic(*D));
10237   } else { /* user may change input matrices when REUSE */
10238     PetscCall(MatProductReplaceMats(A, B, C, *D));
10239   }
10240   PetscCall(MatProductNumeric(*D));
10241   PetscFunctionReturn(PETSC_SUCCESS);
10242 }
10243 
10244 /*@
10245   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10246 
10247   Collective
10248 
10249   Input Parameters:
10250 + mat      - the matrix
10251 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10252 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10253 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10254 
10255   Output Parameter:
10256 . matredundant - redundant matrix
10257 
10258   Level: advanced
10259 
10260   Notes:
10261   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10262   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10263 
10264   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10265   calling it.
10266 
10267   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10268 
10269 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10270 @*/
10271 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10272 {
10273   MPI_Comm       comm;
10274   PetscMPIInt    size;
10275   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10276   Mat_Redundant *redund     = NULL;
10277   PetscSubcomm   psubcomm   = NULL;
10278   MPI_Comm       subcomm_in = subcomm;
10279   Mat           *matseq;
10280   IS             isrow, iscol;
10281   PetscBool      newsubcomm = PETSC_FALSE;
10282 
10283   PetscFunctionBegin;
10284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10285   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10286     PetscAssertPointer(*matredundant, 5);
10287     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10288   }
10289 
10290   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10291   if (size == 1 || nsubcomm == 1) {
10292     if (reuse == MAT_INITIAL_MATRIX) {
10293       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10294     } else {
10295       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");
10296       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10297     }
10298     PetscFunctionReturn(PETSC_SUCCESS);
10299   }
10300 
10301   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10302   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10303   MatCheckPreallocated(mat, 1);
10304 
10305   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10306   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10307     /* create psubcomm, then get subcomm */
10308     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10309     PetscCallMPI(MPI_Comm_size(comm, &size));
10310     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10311 
10312     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10313     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10314     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10315     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10316     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10317     newsubcomm = PETSC_TRUE;
10318     PetscCall(PetscSubcommDestroy(&psubcomm));
10319   }
10320 
10321   /* get isrow, iscol and a local sequential matrix matseq[0] */
10322   if (reuse == MAT_INITIAL_MATRIX) {
10323     mloc_sub = PETSC_DECIDE;
10324     nloc_sub = PETSC_DECIDE;
10325     if (bs < 1) {
10326       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10327       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10328     } else {
10329       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10330       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10331     }
10332     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10333     rstart = rend - mloc_sub;
10334     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10335     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10336     PetscCall(ISSetIdentity(iscol));
10337   } else { /* reuse == MAT_REUSE_MATRIX */
10338     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");
10339     /* retrieve subcomm */
10340     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10341     redund = (*matredundant)->redundant;
10342     isrow  = redund->isrow;
10343     iscol  = redund->iscol;
10344     matseq = redund->matseq;
10345   }
10346   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10347 
10348   /* get matredundant over subcomm */
10349   if (reuse == MAT_INITIAL_MATRIX) {
10350     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10351 
10352     /* create a supporting struct and attach it to C for reuse */
10353     PetscCall(PetscNew(&redund));
10354     (*matredundant)->redundant = redund;
10355     redund->isrow              = isrow;
10356     redund->iscol              = iscol;
10357     redund->matseq             = matseq;
10358     if (newsubcomm) {
10359       redund->subcomm = subcomm;
10360     } else {
10361       redund->subcomm = MPI_COMM_NULL;
10362     }
10363   } else {
10364     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10365   }
10366 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10367   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10368     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10369     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10370   }
10371 #endif
10372   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10373   PetscFunctionReturn(PETSC_SUCCESS);
10374 }
10375 
10376 /*@C
10377   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10378   a given `Mat`. Each submatrix can span multiple procs.
10379 
10380   Collective
10381 
10382   Input Parameters:
10383 + mat     - the matrix
10384 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10385 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10386 
10387   Output Parameter:
10388 . subMat - parallel sub-matrices each spanning a given `subcomm`
10389 
10390   Level: advanced
10391 
10392   Notes:
10393   The submatrix partition across processors is dictated by `subComm` a
10394   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10395   is not restricted to be grouped with consecutive original MPI processes.
10396 
10397   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10398   map directly to the layout of the original matrix [wrt the local
10399   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10400   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10401   the `subMat`. However the offDiagMat looses some columns - and this is
10402   reconstructed with `MatSetValues()`
10403 
10404   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10405 
10406 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10407 @*/
10408 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10409 {
10410   PetscMPIInt commsize, subCommSize;
10411 
10412   PetscFunctionBegin;
10413   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10414   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10415   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10416 
10417   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");
10418   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10419   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10420   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10421   PetscFunctionReturn(PETSC_SUCCESS);
10422 }
10423 
10424 /*@
10425   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10426 
10427   Not Collective
10428 
10429   Input Parameters:
10430 + mat   - matrix to extract local submatrix from
10431 . isrow - local row indices for submatrix
10432 - iscol - local column indices for submatrix
10433 
10434   Output Parameter:
10435 . submat - the submatrix
10436 
10437   Level: intermediate
10438 
10439   Notes:
10440   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10441 
10442   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10443   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10444 
10445   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10446   `MatSetValuesBlockedLocal()` will also be implemented.
10447 
10448   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10449   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10450 
10451 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10452 @*/
10453 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10454 {
10455   PetscFunctionBegin;
10456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10457   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10458   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10459   PetscCheckSameComm(isrow, 2, iscol, 3);
10460   PetscAssertPointer(submat, 4);
10461   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10462 
10463   if (mat->ops->getlocalsubmatrix) {
10464     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10465   } else {
10466     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10467   }
10468   PetscFunctionReturn(PETSC_SUCCESS);
10469 }
10470 
10471 /*@
10472   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10473 
10474   Not Collective
10475 
10476   Input Parameters:
10477 + mat    - matrix to extract local submatrix from
10478 . isrow  - local row indices for submatrix
10479 . iscol  - local column indices for submatrix
10480 - submat - the submatrix
10481 
10482   Level: intermediate
10483 
10484 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10485 @*/
10486 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10487 {
10488   PetscFunctionBegin;
10489   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10490   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10491   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10492   PetscCheckSameComm(isrow, 2, iscol, 3);
10493   PetscAssertPointer(submat, 4);
10494   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10495 
10496   if (mat->ops->restorelocalsubmatrix) {
10497     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10498   } else {
10499     PetscCall(MatDestroy(submat));
10500   }
10501   *submat = NULL;
10502   PetscFunctionReturn(PETSC_SUCCESS);
10503 }
10504 
10505 /*@
10506   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10507 
10508   Collective
10509 
10510   Input Parameter:
10511 . mat - the matrix
10512 
10513   Output Parameter:
10514 . is - if any rows have zero diagonals this contains the list of them
10515 
10516   Level: developer
10517 
10518 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10519 @*/
10520 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10521 {
10522   PetscFunctionBegin;
10523   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10524   PetscValidType(mat, 1);
10525   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10526   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10527 
10528   if (!mat->ops->findzerodiagonals) {
10529     Vec                diag;
10530     const PetscScalar *a;
10531     PetscInt          *rows;
10532     PetscInt           rStart, rEnd, r, nrow = 0;
10533 
10534     PetscCall(MatCreateVecs(mat, &diag, NULL));
10535     PetscCall(MatGetDiagonal(mat, diag));
10536     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10537     PetscCall(VecGetArrayRead(diag, &a));
10538     for (r = 0; r < rEnd - rStart; ++r)
10539       if (a[r] == 0.0) ++nrow;
10540     PetscCall(PetscMalloc1(nrow, &rows));
10541     nrow = 0;
10542     for (r = 0; r < rEnd - rStart; ++r)
10543       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10544     PetscCall(VecRestoreArrayRead(diag, &a));
10545     PetscCall(VecDestroy(&diag));
10546     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10547   } else {
10548     PetscUseTypeMethod(mat, findzerodiagonals, is);
10549   }
10550   PetscFunctionReturn(PETSC_SUCCESS);
10551 }
10552 
10553 /*@
10554   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10555 
10556   Collective
10557 
10558   Input Parameter:
10559 . mat - the matrix
10560 
10561   Output Parameter:
10562 . is - contains the list of rows with off block diagonal entries
10563 
10564   Level: developer
10565 
10566 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10567 @*/
10568 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10569 {
10570   PetscFunctionBegin;
10571   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10572   PetscValidType(mat, 1);
10573   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10574   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10575 
10576   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10577   PetscFunctionReturn(PETSC_SUCCESS);
10578 }
10579 
10580 /*@C
10581   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10582 
10583   Collective; No Fortran Support
10584 
10585   Input Parameter:
10586 . mat - the matrix
10587 
10588   Output Parameter:
10589 . values - the block inverses in column major order (FORTRAN-like)
10590 
10591   Level: advanced
10592 
10593   Notes:
10594   The size of the blocks is determined by the block size of the matrix.
10595 
10596   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10597 
10598   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10599 
10600 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10601 @*/
10602 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10603 {
10604   PetscFunctionBegin;
10605   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10606   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10607   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10608   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10609   PetscFunctionReturn(PETSC_SUCCESS);
10610 }
10611 
10612 /*@C
10613   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10614 
10615   Collective; No Fortran Support
10616 
10617   Input Parameters:
10618 + mat     - the matrix
10619 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10620 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10621 
10622   Output Parameter:
10623 . values - the block inverses in column major order (FORTRAN-like)
10624 
10625   Level: advanced
10626 
10627   Notes:
10628   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10629 
10630   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10631 
10632 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10633 @*/
10634 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10635 {
10636   PetscFunctionBegin;
10637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10638   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10639   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10640   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10641   PetscFunctionReturn(PETSC_SUCCESS);
10642 }
10643 
10644 /*@
10645   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10646 
10647   Collective
10648 
10649   Input Parameters:
10650 + A - the matrix
10651 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10652 
10653   Level: advanced
10654 
10655   Note:
10656   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10657 
10658 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10659 @*/
10660 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10661 {
10662   const PetscScalar *vals;
10663   PetscInt          *dnnz;
10664   PetscInt           m, rstart, rend, bs, i, j;
10665 
10666   PetscFunctionBegin;
10667   PetscCall(MatInvertBlockDiagonal(A, &vals));
10668   PetscCall(MatGetBlockSize(A, &bs));
10669   PetscCall(MatGetLocalSize(A, &m, NULL));
10670   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10671   PetscCall(PetscMalloc1(m / bs, &dnnz));
10672   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10673   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10674   PetscCall(PetscFree(dnnz));
10675   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10676   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10677   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10678   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10679   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10680   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10681   PetscFunctionReturn(PETSC_SUCCESS);
10682 }
10683 
10684 /*@C
10685   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10686   via `MatTransposeColoringCreate()`.
10687 
10688   Collective
10689 
10690   Input Parameter:
10691 . c - coloring context
10692 
10693   Level: intermediate
10694 
10695 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10696 @*/
10697 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10698 {
10699   MatTransposeColoring matcolor = *c;
10700 
10701   PetscFunctionBegin;
10702   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10703   if (--((PetscObject)matcolor)->refct > 0) {
10704     matcolor = NULL;
10705     PetscFunctionReturn(PETSC_SUCCESS);
10706   }
10707 
10708   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10709   PetscCall(PetscFree(matcolor->rows));
10710   PetscCall(PetscFree(matcolor->den2sp));
10711   PetscCall(PetscFree(matcolor->colorforcol));
10712   PetscCall(PetscFree(matcolor->columns));
10713   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10714   PetscCall(PetscHeaderDestroy(c));
10715   PetscFunctionReturn(PETSC_SUCCESS);
10716 }
10717 
10718 /*@C
10719   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10720   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10721   `MatTransposeColoring` to sparse `B`.
10722 
10723   Collective
10724 
10725   Input Parameters:
10726 + coloring - coloring context created with `MatTransposeColoringCreate()`
10727 - B        - sparse matrix
10728 
10729   Output Parameter:
10730 . Btdense - dense matrix $B^T$
10731 
10732   Level: developer
10733 
10734   Note:
10735   These are used internally for some implementations of `MatRARt()`
10736 
10737 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10738 @*/
10739 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10740 {
10741   PetscFunctionBegin;
10742   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10743   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10744   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10745 
10746   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10747   PetscFunctionReturn(PETSC_SUCCESS);
10748 }
10749 
10750 /*@C
10751   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10752   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10753   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10754   $C_{sp}$ from $C_{den}$.
10755 
10756   Collective
10757 
10758   Input Parameters:
10759 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10760 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10761 
10762   Output Parameter:
10763 . Csp - sparse matrix
10764 
10765   Level: developer
10766 
10767   Note:
10768   These are used internally for some implementations of `MatRARt()`
10769 
10770 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10771 @*/
10772 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10773 {
10774   PetscFunctionBegin;
10775   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10776   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10777   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10778 
10779   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10780   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10781   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10782   PetscFunctionReturn(PETSC_SUCCESS);
10783 }
10784 
10785 /*@C
10786   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10787 
10788   Collective
10789 
10790   Input Parameters:
10791 + mat        - the matrix product C
10792 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10793 
10794   Output Parameter:
10795 . color - the new coloring context
10796 
10797   Level: intermediate
10798 
10799 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10800           `MatTransColoringApplyDenToSp()`
10801 @*/
10802 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10803 {
10804   MatTransposeColoring c;
10805   MPI_Comm             comm;
10806 
10807   PetscFunctionBegin;
10808   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10809   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10810   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10811 
10812   c->ctype = iscoloring->ctype;
10813   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10814 
10815   *color = c;
10816   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10817   PetscFunctionReturn(PETSC_SUCCESS);
10818 }
10819 
10820 /*@
10821   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10822   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10823   same, otherwise it will be larger
10824 
10825   Not Collective
10826 
10827   Input Parameter:
10828 . mat - the matrix
10829 
10830   Output Parameter:
10831 . state - the current state
10832 
10833   Level: intermediate
10834 
10835   Notes:
10836   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10837   different matrices
10838 
10839   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10840 
10841   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10842 
10843 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10844 @*/
10845 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10846 {
10847   PetscFunctionBegin;
10848   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10849   *state = mat->nonzerostate;
10850   PetscFunctionReturn(PETSC_SUCCESS);
10851 }
10852 
10853 /*@
10854   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10855   matrices from each processor
10856 
10857   Collective
10858 
10859   Input Parameters:
10860 + comm   - the communicators the parallel matrix will live on
10861 . seqmat - the input sequential matrices
10862 . n      - number of local columns (or `PETSC_DECIDE`)
10863 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10864 
10865   Output Parameter:
10866 . mpimat - the parallel matrix generated
10867 
10868   Level: developer
10869 
10870   Note:
10871   The number of columns of the matrix in EACH processor MUST be the same.
10872 
10873 .seealso: [](ch_matrices), `Mat`
10874 @*/
10875 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10876 {
10877   PetscMPIInt size;
10878 
10879   PetscFunctionBegin;
10880   PetscCallMPI(MPI_Comm_size(comm, &size));
10881   if (size == 1) {
10882     if (reuse == MAT_INITIAL_MATRIX) {
10883       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10884     } else {
10885       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10886     }
10887     PetscFunctionReturn(PETSC_SUCCESS);
10888   }
10889 
10890   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");
10891 
10892   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10893   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10894   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10895   PetscFunctionReturn(PETSC_SUCCESS);
10896 }
10897 
10898 /*@
10899   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10900 
10901   Collective
10902 
10903   Input Parameters:
10904 + A - the matrix to create subdomains from
10905 - N - requested number of subdomains
10906 
10907   Output Parameters:
10908 + n   - number of subdomains resulting on this MPI process
10909 - iss - `IS` list with indices of subdomains on this MPI process
10910 
10911   Level: advanced
10912 
10913   Note:
10914   The number of subdomains must be smaller than the communicator size
10915 
10916 .seealso: [](ch_matrices), `Mat`, `IS`
10917 @*/
10918 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10919 {
10920   MPI_Comm    comm, subcomm;
10921   PetscMPIInt size, rank, color;
10922   PetscInt    rstart, rend, k;
10923 
10924   PetscFunctionBegin;
10925   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10926   PetscCallMPI(MPI_Comm_size(comm, &size));
10927   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10928   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);
10929   *n    = 1;
10930   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10931   color = rank / k;
10932   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10933   PetscCall(PetscMalloc1(1, iss));
10934   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10935   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10936   PetscCallMPI(MPI_Comm_free(&subcomm));
10937   PetscFunctionReturn(PETSC_SUCCESS);
10938 }
10939 
10940 /*@
10941   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10942 
10943   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10944   If they are not the same, uses `MatMatMatMult()`.
10945 
10946   Once the coarse grid problem is constructed, correct for interpolation operators
10947   that are not of full rank, which can legitimately happen in the case of non-nested
10948   geometric multigrid.
10949 
10950   Input Parameters:
10951 + restrct     - restriction operator
10952 . dA          - fine grid matrix
10953 . interpolate - interpolation operator
10954 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10955 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10956 
10957   Output Parameter:
10958 . A - the Galerkin coarse matrix
10959 
10960   Options Database Key:
10961 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10962 
10963   Level: developer
10964 
10965 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10966 @*/
10967 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10968 {
10969   IS  zerorows;
10970   Vec diag;
10971 
10972   PetscFunctionBegin;
10973   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10974   /* Construct the coarse grid matrix */
10975   if (interpolate == restrct) {
10976     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10977   } else {
10978     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10979   }
10980 
10981   /* If the interpolation matrix is not of full rank, A will have zero rows.
10982      This can legitimately happen in the case of non-nested geometric multigrid.
10983      In that event, we set the rows of the matrix to the rows of the identity,
10984      ignoring the equations (as the RHS will also be zero). */
10985 
10986   PetscCall(MatFindZeroRows(*A, &zerorows));
10987 
10988   if (zerorows != NULL) { /* if there are any zero rows */
10989     PetscCall(MatCreateVecs(*A, &diag, NULL));
10990     PetscCall(MatGetDiagonal(*A, diag));
10991     PetscCall(VecISSet(diag, zerorows, 1.0));
10992     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10993     PetscCall(VecDestroy(&diag));
10994     PetscCall(ISDestroy(&zerorows));
10995   }
10996   PetscFunctionReturn(PETSC_SUCCESS);
10997 }
10998 
10999 /*@C
11000   MatSetOperation - Allows user to set a matrix operation for any matrix type
11001 
11002   Logically Collective
11003 
11004   Input Parameters:
11005 + mat - the matrix
11006 . op  - the name of the operation
11007 - f   - the function that provides the operation
11008 
11009   Level: developer
11010 
11011   Example Usage:
11012 .vb
11013   extern PetscErrorCode usermult(Mat, Vec, Vec);
11014 
11015   PetscCall(MatCreateXXX(comm, ..., &A));
11016   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11017 .ve
11018 
11019   Notes:
11020   See the file `include/petscmat.h` for a complete list of matrix
11021   operations, which all have the form MATOP_<OPERATION>, where
11022   <OPERATION> is the name (in all capital letters) of the
11023   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11024 
11025   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11026   sequence as the usual matrix interface routines, since they
11027   are intended to be accessed via the usual matrix interface
11028   routines, e.g.,
11029 .vb
11030   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11031 .ve
11032 
11033   In particular each function MUST return `PETSC_SUCCESS` on success and
11034   nonzero on failure.
11035 
11036   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11037 
11038 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11039 @*/
11040 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11041 {
11042   PetscFunctionBegin;
11043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11044   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11045   (((void (**)(void))mat->ops)[op]) = f;
11046   PetscFunctionReturn(PETSC_SUCCESS);
11047 }
11048 
11049 /*@C
11050   MatGetOperation - Gets a matrix operation for any matrix type.
11051 
11052   Not Collective
11053 
11054   Input Parameters:
11055 + mat - the matrix
11056 - op  - the name of the operation
11057 
11058   Output Parameter:
11059 . f - the function that provides the operation
11060 
11061   Level: developer
11062 
11063   Example Usage:
11064 .vb
11065   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11066 
11067   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11068 .ve
11069 
11070   Notes:
11071   See the file include/petscmat.h for a complete list of matrix
11072   operations, which all have the form MATOP_<OPERATION>, where
11073   <OPERATION> is the name (in all capital letters) of the
11074   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11075 
11076   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11077 
11078 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11079 @*/
11080 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11081 {
11082   PetscFunctionBegin;
11083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11084   *f = (((void (**)(void))mat->ops)[op]);
11085   PetscFunctionReturn(PETSC_SUCCESS);
11086 }
11087 
11088 /*@
11089   MatHasOperation - Determines whether the given matrix supports the particular operation.
11090 
11091   Not Collective
11092 
11093   Input Parameters:
11094 + mat - the matrix
11095 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11096 
11097   Output Parameter:
11098 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11099 
11100   Level: advanced
11101 
11102   Note:
11103   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11104 
11105 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11106 @*/
11107 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11108 {
11109   PetscFunctionBegin;
11110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11111   PetscAssertPointer(has, 3);
11112   if (mat->ops->hasoperation) {
11113     PetscUseTypeMethod(mat, hasoperation, op, has);
11114   } else {
11115     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11116     else {
11117       *has = PETSC_FALSE;
11118       if (op == MATOP_CREATE_SUBMATRIX) {
11119         PetscMPIInt size;
11120 
11121         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11122         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11123       }
11124     }
11125   }
11126   PetscFunctionReturn(PETSC_SUCCESS);
11127 }
11128 
11129 /*@
11130   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11131 
11132   Collective
11133 
11134   Input Parameter:
11135 . mat - the matrix
11136 
11137   Output Parameter:
11138 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11139 
11140   Level: beginner
11141 
11142 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11143 @*/
11144 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11145 {
11146   PetscFunctionBegin;
11147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11148   PetscValidType(mat, 1);
11149   PetscAssertPointer(cong, 2);
11150   if (!mat->rmap || !mat->cmap) {
11151     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11152     PetscFunctionReturn(PETSC_SUCCESS);
11153   }
11154   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11155     PetscCall(PetscLayoutSetUp(mat->rmap));
11156     PetscCall(PetscLayoutSetUp(mat->cmap));
11157     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11158     if (*cong) mat->congruentlayouts = 1;
11159     else mat->congruentlayouts = 0;
11160   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11161   PetscFunctionReturn(PETSC_SUCCESS);
11162 }
11163 
11164 PetscErrorCode MatSetInf(Mat A)
11165 {
11166   PetscFunctionBegin;
11167   PetscUseTypeMethod(A, setinf);
11168   PetscFunctionReturn(PETSC_SUCCESS);
11169 }
11170 
11171 /*@C
11172   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
11173   and possibly removes small values from the graph structure.
11174 
11175   Collective
11176 
11177   Input Parameters:
11178 + A      - the matrix
11179 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11180 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11181 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11182 
11183   Output Parameter:
11184 . graph - the resulting graph
11185 
11186   Level: advanced
11187 
11188 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11189 @*/
11190 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11191 {
11192   PetscFunctionBegin;
11193   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11194   PetscValidType(A, 1);
11195   PetscValidLogicalCollectiveBool(A, scale, 3);
11196   PetscAssertPointer(graph, 5);
11197   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11198   PetscFunctionReturn(PETSC_SUCCESS);
11199 }
11200 
11201 /*@
11202   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11203   meaning the same memory is used for the matrix, and no new memory is allocated.
11204 
11205   Collective
11206 
11207   Input Parameters:
11208 + A    - the matrix
11209 - 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
11210 
11211   Level: intermediate
11212 
11213   Developer Note:
11214   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11215   of the arrays in the data structure are unneeded.
11216 
11217 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11218 @*/
11219 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11220 {
11221   PetscFunctionBegin;
11222   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11223   PetscUseTypeMethod(A, eliminatezeros, keep);
11224   PetscFunctionReturn(PETSC_SUCCESS);
11225 }
11226