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