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