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