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