xref: /petsc/src/mat/interface/matrix.c (revision c8c5c547f526914c69472d8cade615559dc64129)
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_Mults, 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_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36 PetscLogEvent MAT_GetMultiProcBlock;
37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
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    Output Parameter:
61 .  x  - the matrix
62 
63    Example:
64 .vb
65      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
66      MatSetRandom(x,rctx);
67      PetscRandomDestroy(rctx);
68 .ve
69 
70    Level: intermediate
71 
72    Notes:
73    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
74 
75    for sparse matrices that already have locations it fills the locations with random numbers.
76 
77    It generates an error if used on sparse matrices that have not been preallocated.
78 
79 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
80 @*/
81 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
82 {
83   PetscRandom randObj = NULL;
84 
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
87   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
88   PetscValidType(x, 1);
89   MatCheckPreallocated(x, 1);
90 
91   if (!rctx) {
92     MPI_Comm comm;
93     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
94     PetscCall(PetscRandomCreate(comm, &randObj));
95     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
96     PetscCall(PetscRandomSetFromOptions(randObj));
97     rctx = randObj;
98   }
99   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
100   PetscUseTypeMethod(x, setrandom, rctx);
101   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
102 
103   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
104   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
105   PetscCall(PetscRandomDestroy(&randObj));
106   PetscFunctionReturn(PETSC_SUCCESS);
107 }
108 
109 /*@
110    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
111 
112    Logically Collective
113 
114    Input Parameter:
115 .  mat - the factored matrix
116 
117    Output Parameters:
118 +  pivot - the pivot value computed
119 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
120          the share the matrix
121 
122    Level: advanced
123 
124    Notes:
125     This routine does not work for factorizations done with external packages.
126 
127     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
128 
129     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
130 
131 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
132           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
133 @*/
134 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
135 {
136   PetscFunctionBegin;
137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
138   PetscValidRealPointer(pivot, 2);
139   PetscValidIntPointer(row, 3);
140   *pivot = mat->factorerror_zeropivot_value;
141   *row   = mat->factorerror_zeropivot_row;
142   PetscFunctionReturn(PETSC_SUCCESS);
143 }
144 
145 /*@
146    MatFactorGetError - gets the error code from a factorization
147 
148    Logically Collective
149 
150    Input Parameters:
151 .  mat - the factored matrix
152 
153    Output Parameter:
154 .  err  - the error code
155 
156    Level: advanced
157 
158    Note:
159     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
160 
161 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
162           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
163 @*/
164 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
165 {
166   PetscFunctionBegin;
167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
168   PetscValidPointer(err, 2);
169   *err = mat->factorerrortype;
170   PetscFunctionReturn(PETSC_SUCCESS);
171 }
172 
173 /*@
174    MatFactorClearError - clears the error code in a factorization
175 
176    Logically Collective
177 
178    Input Parameter:
179 .  mat - the factored matrix
180 
181    Level: developer
182 
183    Note:
184     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
185 
186 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
187           `MatGetErrorCode()`, `MatFactorError`
188 @*/
189 PetscErrorCode MatFactorClearError(Mat mat)
190 {
191   PetscFunctionBegin;
192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
193   mat->factorerrortype             = MAT_FACTOR_NOERROR;
194   mat->factorerror_zeropivot_value = 0.0;
195   mat->factorerror_zeropivot_row   = 0;
196   PetscFunctionReturn(PETSC_SUCCESS);
197 }
198 
199 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
200 {
201   Vec                r, l;
202   const PetscScalar *al;
203   PetscInt           i, nz, gnz, N, n;
204 
205   PetscFunctionBegin;
206   PetscCall(MatCreateVecs(mat, &r, &l));
207   if (!cols) { /* nonzero rows */
208     PetscCall(MatGetSize(mat, &N, NULL));
209     PetscCall(MatGetLocalSize(mat, &n, NULL));
210     PetscCall(VecSet(l, 0.0));
211     PetscCall(VecSetRandom(r, NULL));
212     PetscCall(MatMult(mat, r, l));
213     PetscCall(VecGetArrayRead(l, &al));
214   } else { /* nonzero columns */
215     PetscCall(MatGetSize(mat, NULL, &N));
216     PetscCall(MatGetLocalSize(mat, NULL, &n));
217     PetscCall(VecSet(r, 0.0));
218     PetscCall(VecSetRandom(l, NULL));
219     PetscCall(MatMultTranspose(mat, l, r));
220     PetscCall(VecGetArrayRead(r, &al));
221   }
222   if (tol <= 0.0) {
223     for (i = 0, nz = 0; i < n; i++)
224       if (al[i] != 0.0) nz++;
225   } else {
226     for (i = 0, nz = 0; i < n; i++)
227       if (PetscAbsScalar(al[i]) > tol) nz++;
228   }
229   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
230   if (gnz != N) {
231     PetscInt *nzr;
232     PetscCall(PetscMalloc1(nz, &nzr));
233     if (nz) {
234       if (tol < 0) {
235         for (i = 0, nz = 0; i < n; i++)
236           if (al[i] != 0.0) nzr[nz++] = i;
237       } else {
238         for (i = 0, nz = 0; i < n; i++)
239           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
240       }
241     }
242     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
243   } else *nonzero = NULL;
244   if (!cols) { /* nonzero rows */
245     PetscCall(VecRestoreArrayRead(l, &al));
246   } else {
247     PetscCall(VecRestoreArrayRead(r, &al));
248   }
249   PetscCall(VecDestroy(&l));
250   PetscCall(VecDestroy(&r));
251   PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 
254 /*@
255       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
256 
257   Input Parameter:
258 .    A  - the matrix
259 
260   Output Parameter:
261 .    keptrows - the rows that are not completely zero
262 
263   Level: intermediate
264 
265   Note:
266     `keptrows` is set to `NULL` if all rows are nonzero.
267 
268 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
269  @*/
270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
271 {
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
274   PetscValidType(mat, 1);
275   PetscValidPointer(keptrows, 2);
276   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
277   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
278   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
279   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
280   PetscFunctionReturn(PETSC_SUCCESS);
281 }
282 
283 /*@
284       MatFindZeroRows - Locate all rows that are completely zero in the matrix
285 
286   Input Parameter:
287 .    A  - the matrix
288 
289   Output Parameter:
290 .    zerorows - the rows that are completely zero
291 
292   Level: intermediate
293 
294   Note:
295     `zerorows` is set to `NULL` if no rows are zero.
296 
297 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
298  @*/
299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
300 {
301   IS       keptrows;
302   PetscInt m, n;
303 
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
306   PetscValidType(mat, 1);
307   PetscValidPointer(zerorows, 2);
308   PetscCall(MatFindNonzeroRows(mat, &keptrows));
309   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
310      In keeping with this convention, we set zerorows to NULL if there are no zero
311      rows. */
312   if (keptrows == NULL) {
313     *zerorows = NULL;
314   } else {
315     PetscCall(MatGetOwnershipRange(mat, &m, &n));
316     PetscCall(ISComplement(keptrows, m, n, zerorows));
317     PetscCall(ISDestroy(&keptrows));
318   }
319   PetscFunctionReturn(PETSC_SUCCESS);
320 }
321 
322 /*@
323    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
324 
325    Not Collective
326 
327    Input Parameters:
328 .   A - the matrix
329 
330    Output Parameters:
331 .   a - the diagonal part (which is a SEQUENTIAL matrix)
332 
333    Level: advanced
334 
335    Notes:
336    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
337 
338    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
339 
340 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
341 @*/
342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
343 {
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
346   PetscValidType(A, 1);
347   PetscValidPointer(a, 2);
348   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
349   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
350   else {
351     PetscMPIInt size;
352 
353     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
354     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
355     *a = A;
356   }
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /*@
361    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
362 
363    Collective
364 
365    Input Parameters:
366 .  mat - the matrix
367 
368    Output Parameter:
369 .   trace - the sum of the diagonal entries
370 
371    Level: advanced
372 
373 .seealso: [](chapter_matrices), `Mat`
374 @*/
375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
376 {
377   Vec diag;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
381   PetscValidScalarPointer(trace, 2);
382   PetscCall(MatCreateVecs(mat, &diag, NULL));
383   PetscCall(MatGetDiagonal(mat, diag));
384   PetscCall(VecSum(diag, trace));
385   PetscCall(VecDestroy(&diag));
386   PetscFunctionReturn(PETSC_SUCCESS);
387 }
388 
389 /*@
390    MatRealPart - Zeros out the imaginary part of the matrix
391 
392    Logically Collective
393 
394    Input Parameters:
395 .  mat - the matrix
396 
397    Level: advanced
398 
399 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
400 @*/
401 PetscErrorCode MatRealPart(Mat mat)
402 {
403   PetscFunctionBegin;
404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
405   PetscValidType(mat, 1);
406   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
407   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
408   MatCheckPreallocated(mat, 1);
409   PetscUseTypeMethod(mat, realpart);
410   PetscFunctionReturn(PETSC_SUCCESS);
411 }
412 
413 /*@C
414    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
415 
416    Collective
417 
418    Input Parameter:
419 .  mat - the matrix
420 
421    Output Parameters:
422 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
423 -   ghosts - the global indices of the ghost points
424 
425    Level: advanced
426 
427    Note:
428    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
429 
430 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
431 @*/
432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
433 {
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
436   PetscValidType(mat, 1);
437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
440   else {
441     if (nghosts) *nghosts = 0;
442     if (ghosts) *ghosts = NULL;
443   }
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
449 
450    Logically Collective
451 
452    Input Parameters:
453 .  mat - the matrix
454 
455    Level: advanced
456 
457 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
458 @*/
459 PetscErrorCode MatImaginaryPart(Mat mat)
460 {
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
463   PetscValidType(mat, 1);
464   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
465   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
466   MatCheckPreallocated(mat, 1);
467   PetscUseTypeMethod(mat, imaginarypart);
468   PetscFunctionReturn(PETSC_SUCCESS);
469 }
470 
471 /*@
472    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
473 
474    Not Collective
475 
476    Input Parameter:
477 .  mat - the matrix
478 
479    Output Parameters:
480 +  missing - is any diagonal missing
481 -  dd - first diagonal entry that is missing (optional) on this process
482 
483    Level: advanced
484 
485 .seealso: [](chapter_matrices), `Mat`
486 @*/
487 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
488 {
489   PetscFunctionBegin;
490   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
491   PetscValidType(mat, 1);
492   PetscValidBoolPointer(missing, 2);
493   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
494   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
495   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
496   PetscFunctionReturn(PETSC_SUCCESS);
497 }
498 
499 /*@C
500    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
501    for each row that you get to ensure that your application does
502    not bleed memory.
503 
504    Not Collective
505 
506    Input Parameters:
507 +  mat - the matrix
508 -  row - the row to get
509 
510    Output Parameters:
511 +  ncols -  if not `NULL`, the number of nonzeros in the row
512 .  cols - if not `NULL`, the column numbers
513 -  vals - if not `NULL`, the values
514 
515    Level: advanced
516 
517    Notes:
518    This routine is provided for people who need to have direct access
519    to the structure of a matrix.  We hope that we provide enough
520    high-level matrix routines that few users will need it.
521 
522    `MatGetRow()` always returns 0-based column indices, regardless of
523    whether the internal representation is 0-based (default) or 1-based.
524 
525    For better efficiency, set cols and/or vals to `NULL` if you do
526    not wish to extract these quantities.
527 
528    The user can only examine the values extracted with `MatGetRow()`;
529    the values cannot be altered.  To change the matrix entries, one
530    must use `MatSetValues()`.
531 
532    You can only have one call to `MatGetRow()` outstanding for a particular
533    matrix at a time, per processor. `MatGetRow()` can only obtain rows
534    associated with the given processor, it cannot get rows from the
535    other processors; for that we suggest using `MatCreateSubMatrices()`, then
536    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
537    is in the global number of rows.
538 
539    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
540 
541    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
542 
543    Fortran Note:
544    The calling sequence is
545 .vb
546    MatGetRow(matrix,row,ncols,cols,values,ierr)
547          Mat     matrix (input)
548          integer row    (input)
549          integer ncols  (output)
550          integer cols(maxcols) (output)
551          double precision (or double complex) values(maxcols) output
552 .ve
553    where maxcols >= maximum nonzeros in any row of the matrix.
554 
555    Caution:
556    Do not try to change the contents of the output arrays (cols and vals).
557    In some cases, this may corrupt the matrix.
558 
559 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560 @*/
561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562 {
563   PetscInt incols;
564 
565   PetscFunctionBegin;
566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
567   PetscValidType(mat, 1);
568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570   MatCheckPreallocated(mat, 1);
571   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);
572   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
574   if (ncols) *ncols = incols;
575   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576   PetscFunctionReturn(PETSC_SUCCESS);
577 }
578 
579 /*@
580    MatConjugate - replaces the matrix values with their complex conjugates
581 
582    Logically Collective
583 
584    Input Parameters:
585 .  mat - the matrix
586 
587    Level: advanced
588 
589 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590 @*/
591 PetscErrorCode MatConjugate(Mat mat)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
597     PetscUseTypeMethod(mat, conjugate);
598     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599   }
600   PetscFunctionReturn(PETSC_SUCCESS);
601 }
602 
603 /*@C
604    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
605 
606    Not Collective
607 
608    Input Parameters:
609 +  mat - the matrix
610 .  row - the row to get
611 .  ncols, cols - the number of nonzeros and their columns
612 -  vals - if nonzero the column values
613 
614    Level: advanced
615 
616    Notes:
617    This routine should be called after you have finished examining the entries.
618 
619    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
620    us of the array after it has been restored. If you pass `NULL`, it will
621    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
622 
623    Fortran Notes:
624    The calling sequence is
625 .vb
626    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
627       Mat     matrix (input)
628       integer row    (input)
629       integer ncols  (output)
630       integer cols(maxcols) (output)
631       double precision (or double complex) values(maxcols) output
632 .ve
633    Where maxcols >= maximum nonzeros in any row of the matrix.
634 
635    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
636    before another call to `MatGetRow()` can be made.
637 
638 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
639 @*/
640 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
641 {
642   PetscFunctionBegin;
643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
644   if (ncols) PetscValidIntPointer(ncols, 3);
645   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
646   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
647   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
648   if (ncols) *ncols = 0;
649   if (cols) *cols = NULL;
650   if (vals) *vals = NULL;
651   PetscFunctionReturn(PETSC_SUCCESS);
652 }
653 
654 /*@
655    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
656    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
657 
658    Not Collective
659 
660    Input Parameters:
661 .  mat - the matrix
662 
663    Level: advanced
664 
665    Note:
666    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.
667 
668 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
669 @*/
670 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
671 {
672   PetscFunctionBegin;
673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
674   PetscValidType(mat, 1);
675   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
676   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
677   MatCheckPreallocated(mat, 1);
678   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
679   PetscUseTypeMethod(mat, getrowuppertriangular);
680   PetscFunctionReturn(PETSC_SUCCESS);
681 }
682 
683 /*@
684    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
685 
686    Not Collective
687 
688    Input Parameters:
689 .  mat - the matrix
690 
691    Level: advanced
692 
693    Note:
694    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
695 
696 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
697 @*/
698 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
699 {
700   PetscFunctionBegin;
701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
702   PetscValidType(mat, 1);
703   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
704   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
705   MatCheckPreallocated(mat, 1);
706   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
707   PetscUseTypeMethod(mat, restorerowuppertriangular);
708   PetscFunctionReturn(PETSC_SUCCESS);
709 }
710 
711 /*@C
712    MatSetOptionsPrefix - Sets the prefix used for searching for all
713    `Mat` options in the database.
714 
715    Logically Collective
716 
717    Input Parameters:
718 +  A - the matrix
719 -  prefix - the prefix to prepend to all option names
720 
721    Level: advanced
722 
723    Notes:
724    A hyphen (-) must NOT be given at the beginning of the prefix name.
725    The first character of all runtime options is AUTOMATICALLY the hyphen.
726 
727    This is NOT used for options for the factorization of the matrix. Normally the
728    prefix is automatically passed in from the PC calling the factorization. To set
729    it directly use  `MatSetOptionsPrefixFactor()`
730 
731 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
732 @*/
733 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
734 {
735   PetscFunctionBegin;
736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
737   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
738   PetscFunctionReturn(PETSC_SUCCESS);
739 }
740 
741 /*@C
742    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
743    for matrices created with `MatGetFactor()`
744 
745    Logically Collective
746 
747    Input Parameters:
748 +  A - the matrix
749 -  prefix - the prefix to prepend to all option names for the factored matrix
750 
751    Level: developer
752 
753    Notes:
754    A hyphen (-) must NOT be given at the beginning of the prefix name.
755    The first character of all runtime options is AUTOMATICALLY the hyphen.
756 
757    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
758    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
759 
760 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
761 @*/
762 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
763 {
764   PetscFunctionBegin;
765   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
766   if (prefix) {
767     PetscValidCharPointer(prefix, 2);
768     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
769     if (prefix != A->factorprefix) {
770       PetscCall(PetscFree(A->factorprefix));
771       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
772     }
773   } else PetscCall(PetscFree(A->factorprefix));
774   PetscFunctionReturn(PETSC_SUCCESS);
775 }
776 
777 /*@C
778    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
779    for matrices created with `MatGetFactor()`
780 
781    Logically Collective
782 
783    Input Parameters:
784 +  A - the matrix
785 -  prefix - the prefix to prepend to all option names for the factored matrix
786 
787    Level: developer
788 
789    Notes:
790    A hyphen (-) must NOT be given at the beginning of the prefix name.
791    The first character of all runtime options is AUTOMATICALLY the hyphen.
792 
793    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
794    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
795 
796 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
797           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
798           `MatSetOptionsPrefix()`
799 @*/
800 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
801 {
802   char  *buf = A->factorprefix;
803   size_t len1, len2;
804 
805   PetscFunctionBegin;
806   PetscValidHeader(A, 1);
807   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
808   if (!buf) {
809     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
810     PetscFunctionReturn(PETSC_SUCCESS);
811   }
812   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
813 
814   PetscCall(PetscStrlen(prefix, &len1));
815   PetscCall(PetscStrlen(buf, &len2));
816   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
817   PetscCall(PetscStrcpy(A->factorprefix, buf));
818   PetscCall(PetscStrcat(A->factorprefix, prefix));
819   PetscCall(PetscFree(buf));
820   PetscFunctionReturn(PETSC_SUCCESS);
821 }
822 
823 /*@C
824    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
825    matrix options in the database.
826 
827    Logically Collective
828 
829    Input Parameters:
830 +  A - the matrix
831 -  prefix - the prefix to prepend to all option names
832 
833    Level: advanced
834 
835    Note:
836    A hyphen (-) must NOT be given at the beginning of the prefix name.
837    The first character of all runtime options is AUTOMATICALLY the hyphen.
838 
839 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
840 @*/
841 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
842 {
843   PetscFunctionBegin;
844   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
845   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
846   PetscFunctionReturn(PETSC_SUCCESS);
847 }
848 
849 /*@C
850    MatGetOptionsPrefix - Gets the prefix used for searching for all
851    matrix options in the database.
852 
853    Not Collective
854 
855    Input Parameter:
856 .  A - the matrix
857 
858    Output Parameter:
859 .  prefix - pointer to the prefix string used
860 
861    Level: advanced
862 
863    Fortran Note:
864    The user should pass in a string `prefix` of
865    sufficient length to hold the prefix.
866 
867 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
868 @*/
869 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
870 {
871   PetscFunctionBegin;
872   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
873   PetscValidPointer(prefix, 2);
874   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
875   PetscFunctionReturn(PETSC_SUCCESS);
876 }
877 
878 /*@
879    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
880 
881    Collective
882 
883    Input Parameters:
884 .  A - the matrix
885 
886    Level: beginner
887 
888    Notes:
889    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
890 
891    Users can reset the preallocation to access the original memory.
892 
893    Currently only supported for  `MATAIJ` matrices.
894 
895 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
896 @*/
897 PetscErrorCode MatResetPreallocation(Mat A)
898 {
899   PetscFunctionBegin;
900   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
901   PetscValidType(A, 1);
902   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
903   PetscFunctionReturn(PETSC_SUCCESS);
904 }
905 
906 /*@
907    MatSetUp - Sets up the internal matrix data structures for later use.
908 
909    Collective
910 
911    Input Parameters:
912 .  A - the matrix
913 
914    Level: intermediate
915 
916    Notes:
917    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
918    setting values in the matrix.
919 
920    If a suitable preallocation routine is used, this function does not need to be called.
921 
922    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
923 
924 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
925 @*/
926 PetscErrorCode MatSetUp(Mat A)
927 {
928   PetscFunctionBegin;
929   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
930   if (!((PetscObject)A)->type_name) {
931     PetscMPIInt size;
932 
933     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
934     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
935   }
936   if (!A->preallocated) PetscTryTypeMethod(A, setup);
937   PetscCall(PetscLayoutSetUp(A->rmap));
938   PetscCall(PetscLayoutSetUp(A->cmap));
939   A->preallocated = PETSC_TRUE;
940   PetscFunctionReturn(PETSC_SUCCESS);
941 }
942 
943 #if defined(PETSC_HAVE_SAWS)
944   #include <petscviewersaws.h>
945 #endif
946 
947 /*@C
948    MatViewFromOptions - View properties of the matrix based on options set in the options database
949 
950    Collective
951 
952    Input Parameters:
953 +  A - the matrix
954 .  obj - optional additional object that provides the options prefix to use
955 -  name - command line option
956 
957   Options Database Key:
958 .  -mat_view [viewertype]:... - the viewer and its options
959 
960    Level: intermediate
961 
962   Notes:
963 .vb
964     If no value is provided ascii:stdout is used
965        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
966                                                   for example ascii::ascii_info prints just the information about the object not all details
967                                                   unless :append is given filename opens in write mode, overwriting what was already there
968        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
969        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
970        socket[:port]                             defaults to the standard output port
971        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
972 .ve
973 
974 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
975 @*/
976 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
977 {
978   PetscFunctionBegin;
979   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
980   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
981   PetscFunctionReturn(PETSC_SUCCESS);
982 }
983 
984 /*@C
985    MatView - display information about a matrix in a variety ways
986 
987    Collective
988 
989    Input Parameters:
990 +  mat - the matrix
991 -  viewer - visualization context
992 
993   Notes:
994   The available visualization contexts include
995 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
996 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
997 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
998 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
999 
1000    The user can open alternative visualization contexts with
1001 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1002 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1003          specified file; corresponding input uses MatLoad()
1004 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1005          an X window display
1006 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1007          Currently only the sequential dense and AIJ
1008          matrix types support the Socket viewer.
1009 
1010    The user can call `PetscViewerPushFormat()` to specify the output
1011    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1012    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1013 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1014 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1015 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1016 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1017          format common among all matrix types
1018 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1019          format (which is in many cases the same as the default)
1020 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1021          size and structure (not the matrix entries)
1022 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1023          the matrix structure
1024 
1025    Options Database Keys:
1026 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1027 .  -mat_view ::ascii_info_detail - Prints more detailed info
1028 .  -mat_view - Prints matrix in ASCII format
1029 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1030 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1031 .  -display <name> - Sets display name (default is host)
1032 .  -draw_pause <sec> - Sets number of seconds to pause after display
1033 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1034 .  -viewer_socket_machine <machine> -
1035 .  -viewer_socket_port <port> -
1036 .  -mat_view binary - save matrix to file in binary format
1037 -  -viewer_binary_filename <name> -
1038 
1039    Level: beginner
1040 
1041    Notes:
1042     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1043     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1044 
1045     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1046 
1047     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1048       viewer is used.
1049 
1050       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1051       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1052 
1053       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1054       and then use the following mouse functions.
1055 .vb
1056   left mouse: zoom in
1057   middle mouse: zoom out
1058   right mouse: continue with the simulation
1059 .ve
1060 
1061 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1062           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1063 @*/
1064 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1065 {
1066   PetscInt          rows, cols, rbs, cbs;
1067   PetscBool         isascii, isstring, issaws;
1068   PetscViewerFormat format;
1069   PetscMPIInt       size;
1070 
1071   PetscFunctionBegin;
1072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1073   PetscValidType(mat, 1);
1074   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1075   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1076   PetscCheckSameComm(mat, 1, viewer, 2);
1077 
1078   PetscCall(PetscViewerGetFormat(viewer, &format));
1079   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1080   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1081 
1082   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1083   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1084   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1085   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");
1086 
1087   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1088   if (isascii) {
1089     if (!mat->preallocated) {
1090       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1091       PetscFunctionReturn(PETSC_SUCCESS);
1092     }
1093     if (!mat->assembled) {
1094       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1095       PetscFunctionReturn(PETSC_SUCCESS);
1096     }
1097     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1098     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1099       MatNullSpace nullsp, transnullsp;
1100 
1101       PetscCall(PetscViewerASCIIPushTab(viewer));
1102       PetscCall(MatGetSize(mat, &rows, &cols));
1103       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1104       if (rbs != 1 || cbs != 1) {
1105         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1106         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1107       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1108       if (mat->factortype) {
1109         MatSolverType solver;
1110         PetscCall(MatFactorGetSolverType(mat, &solver));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1112       }
1113       if (mat->ops->getinfo) {
1114         MatInfo info;
1115         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1116         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1117         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1118       }
1119       PetscCall(MatGetNullSpace(mat, &nullsp));
1120       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1121       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1122       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1123       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1124       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1125       PetscCall(PetscViewerASCIIPushTab(viewer));
1126       PetscCall(MatProductView(mat, viewer));
1127       PetscCall(PetscViewerASCIIPopTab(viewer));
1128     }
1129   } else if (issaws) {
1130 #if defined(PETSC_HAVE_SAWS)
1131     PetscMPIInt rank;
1132 
1133     PetscCall(PetscObjectName((PetscObject)mat));
1134     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1135     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1136 #endif
1137   } else if (isstring) {
1138     const char *type;
1139     PetscCall(MatGetType(mat, &type));
1140     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1141     PetscTryTypeMethod(mat, view, viewer);
1142   }
1143   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1144     PetscCall(PetscViewerASCIIPushTab(viewer));
1145     PetscUseTypeMethod(mat, viewnative, viewer);
1146     PetscCall(PetscViewerASCIIPopTab(viewer));
1147   } else if (mat->ops->view) {
1148     PetscCall(PetscViewerASCIIPushTab(viewer));
1149     PetscUseTypeMethod(mat, view, viewer);
1150     PetscCall(PetscViewerASCIIPopTab(viewer));
1151   }
1152   if (isascii) {
1153     PetscCall(PetscViewerGetFormat(viewer, &format));
1154     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1155   }
1156   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1157   PetscFunctionReturn(PETSC_SUCCESS);
1158 }
1159 
1160 #if defined(PETSC_USE_DEBUG)
1161   #include <../src/sys/totalview/tv_data_display.h>
1162 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1163 {
1164   TV_add_row("Local rows", "int", &mat->rmap->n);
1165   TV_add_row("Local columns", "int", &mat->cmap->n);
1166   TV_add_row("Global rows", "int", &mat->rmap->N);
1167   TV_add_row("Global columns", "int", &mat->cmap->N);
1168   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1169   return TV_format_OK;
1170 }
1171 #endif
1172 
1173 /*@C
1174    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1175    with `MatView()`.  The matrix format is determined from the options database.
1176    Generates a parallel MPI matrix if the communicator has more than one
1177    processor.  The default matrix type is `MATAIJ`.
1178 
1179    Collective
1180 
1181    Input Parameters:
1182 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1183             or some related function before a call to `MatLoad()`
1184 -  viewer - binary/HDF5 file viewer
1185 
1186    Options Database Keys:
1187    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1188    block size
1189 .    -matload_block_size <bs> - set block size
1190 
1191    Level: beginner
1192 
1193    Notes:
1194    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1195    `Mat` before calling this routine if you wish to set it from the options database.
1196 
1197    `MatLoad()` automatically loads into the options database any options
1198    given in the file filename.info where filename is the name of the file
1199    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1200    file will be ignored if you use the -viewer_binary_skip_info option.
1201 
1202    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1203    sets the default matrix type AIJ and sets the local and global sizes.
1204    If type and/or size is already set, then the same are used.
1205 
1206    In parallel, each processor can load a subset of rows (or the
1207    entire matrix).  This routine is especially useful when a large
1208    matrix is stored on disk and only part of it is desired on each
1209    processor.  For example, a parallel solver may access only some of
1210    the rows from each processor.  The algorithm used here reads
1211    relatively small blocks of data rather than reading the entire
1212    matrix and then subsetting it.
1213 
1214    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1215    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1216    or the sequence like
1217 .vb
1218     `PetscViewer` v;
1219     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1220     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1221     `PetscViewerSetFromOptions`(v);
1222     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1223     `PetscViewerFileSetName`(v,"datafile");
1224 .ve
1225    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1226 $ -viewer_type {binary,hdf5}
1227 
1228    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1229    and src/mat/tutorials/ex10.c with the second approach.
1230 
1231    Notes:
1232    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1233    is read onto rank 0 and then shipped to its destination rank, one after another.
1234    Multiple objects, both matrices and vectors, can be stored within the same file.
1235    Their PetscObject name is ignored; they are loaded in the order of their storage.
1236 
1237    Most users should not need to know the details of the binary storage
1238    format, since `MatLoad()` and `MatView()` completely hide these details.
1239    But for anyone who's interested, the standard binary matrix storage
1240    format is
1241 
1242 .vb
1243     PetscInt    MAT_FILE_CLASSID
1244     PetscInt    number of rows
1245     PetscInt    number of columns
1246     PetscInt    total number of nonzeros
1247     PetscInt    *number nonzeros in each row
1248     PetscInt    *column indices of all nonzeros (starting index is zero)
1249     PetscScalar *values of all nonzeros
1250 .ve
1251 
1252    PETSc automatically does the byte swapping for
1253 machines that store the bytes reversed. Thus if you write your own binary
1254 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1255 and `PetscBinaryWrite()` to see how this may be done.
1256 
1257    Notes:
1258    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1259    Each processor's chunk is loaded independently by its owning rank.
1260    Multiple objects, both matrices and vectors, can be stored within the same file.
1261    They are looked up by their PetscObject name.
1262 
1263    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1264    by default the same structure and naming of the AIJ arrays and column count
1265    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1266 $    save example.mat A b -v7.3
1267    can be directly read by this routine (see Reference 1 for details).
1268 
1269    Depending on your MATLAB version, this format might be a default,
1270    otherwise you can set it as default in Preferences.
1271 
1272    Unless -nocompression flag is used to save the file in MATLAB,
1273    PETSc must be configured with ZLIB package.
1274 
1275    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1276 
1277    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1278 
1279    Corresponding `MatView()` is not yet implemented.
1280 
1281    The loaded matrix is actually a transpose of the original one in MATLAB,
1282    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1283    With this format, matrix is automatically transposed by PETSc,
1284    unless the matrix is marked as SPD or symmetric
1285    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1286 
1287    References:
1288 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1289 
1290 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1291  @*/
1292 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1293 {
1294   PetscBool flg;
1295 
1296   PetscFunctionBegin;
1297   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1298   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1299 
1300   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1301 
1302   flg = PETSC_FALSE;
1303   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1304   if (flg) {
1305     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1306     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1307   }
1308   flg = PETSC_FALSE;
1309   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1310   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1311 
1312   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1313   PetscUseTypeMethod(mat, load, viewer);
1314   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1315   PetscFunctionReturn(PETSC_SUCCESS);
1316 }
1317 
1318 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1319 {
1320   Mat_Redundant *redund = *redundant;
1321 
1322   PetscFunctionBegin;
1323   if (redund) {
1324     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1325       PetscCall(ISDestroy(&redund->isrow));
1326       PetscCall(ISDestroy(&redund->iscol));
1327       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1328     } else {
1329       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1330       PetscCall(PetscFree(redund->sbuf_j));
1331       PetscCall(PetscFree(redund->sbuf_a));
1332       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1333         PetscCall(PetscFree(redund->rbuf_j[i]));
1334         PetscCall(PetscFree(redund->rbuf_a[i]));
1335       }
1336       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1337     }
1338 
1339     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1340     PetscCall(PetscFree(redund));
1341   }
1342   PetscFunctionReturn(PETSC_SUCCESS);
1343 }
1344 
1345 /*@C
1346    MatDestroy - Frees space taken by a matrix.
1347 
1348    Collective
1349 
1350    Input Parameter:
1351 .  A - the matrix
1352 
1353    Level: beginner
1354 
1355    Developer Note:
1356    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1357    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1358    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1359    if changes are needed here.
1360 
1361 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1362 @*/
1363 PetscErrorCode MatDestroy(Mat *A)
1364 {
1365   PetscFunctionBegin;
1366   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1367   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1368   if (--((PetscObject)(*A))->refct > 0) {
1369     *A = NULL;
1370     PetscFunctionReturn(PETSC_SUCCESS);
1371   }
1372 
1373   /* if memory was published with SAWs then destroy it */
1374   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1375   PetscTryTypeMethod((*A), destroy);
1376 
1377   PetscCall(PetscFree((*A)->factorprefix));
1378   PetscCall(PetscFree((*A)->defaultvectype));
1379   PetscCall(PetscFree((*A)->defaultrandtype));
1380   PetscCall(PetscFree((*A)->bsizes));
1381   PetscCall(PetscFree((*A)->solvertype));
1382   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1383   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1384   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1385   PetscCall(MatProductClear(*A));
1386   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1387   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1388   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1389   PetscCall(MatDestroy(&(*A)->schur));
1390   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1391   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1392   PetscCall(PetscHeaderDestroy(A));
1393   PetscFunctionReturn(PETSC_SUCCESS);
1394 }
1395 
1396 /*@C
1397    MatSetValues - Inserts or adds a block of values into a matrix.
1398    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1399    MUST be called after all calls to `MatSetValues()` have been completed.
1400 
1401    Not Collective
1402 
1403    Input Parameters:
1404 +  mat - the matrix
1405 .  v - a logically two-dimensional array of values
1406 .  m, idxm - the number of rows and their global indices
1407 .  n, idxn - the number of columns and their global indices
1408 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1409 
1410    Level: beginner
1411 
1412    Notes:
1413    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1414 
1415    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1416    options cannot be mixed without intervening calls to the assembly
1417    routines.
1418 
1419    `MatSetValues()` uses 0-based row and column numbers in Fortran
1420    as well as in C.
1421 
1422    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1423    simply ignored. This allows easily inserting element stiffness matrices
1424    with homogeneous Dirchlet boundary conditions that you don't want represented
1425    in the matrix.
1426 
1427    Efficiency Alert:
1428    The routine `MatSetValuesBlocked()` may offer much better efficiency
1429    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1430 
1431    Developer Note:
1432    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1433    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1434 
1435 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1436           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1437 @*/
1438 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1439 {
1440   PetscFunctionBeginHot;
1441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1442   PetscValidType(mat, 1);
1443   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1444   PetscValidIntPointer(idxm, 3);
1445   PetscValidIntPointer(idxn, 5);
1446   MatCheckPreallocated(mat, 1);
1447 
1448   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1449   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1450 
1451   if (PetscDefined(USE_DEBUG)) {
1452     PetscInt i, j;
1453 
1454     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1455     for (i = 0; i < m; i++) {
1456       for (j = 0; j < n; j++) {
1457         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1458 #if defined(PETSC_USE_COMPLEX)
1459           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]);
1460 #else
1461           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]);
1462 #endif
1463       }
1464     }
1465     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);
1466     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);
1467   }
1468 
1469   if (mat->assembled) {
1470     mat->was_assembled = PETSC_TRUE;
1471     mat->assembled     = PETSC_FALSE;
1472   }
1473   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1474   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1475   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1476   PetscFunctionReturn(PETSC_SUCCESS);
1477 }
1478 
1479 /*@C
1480    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1481    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1482    MUST be called after all calls to `MatSetValues()` have been completed.
1483 
1484    Not Collective
1485 
1486    Input Parameters:
1487 +  mat - the matrix
1488 .  v - a logically two-dimensional array of values
1489 .  ism - the rows to provide
1490 .  isn - the columns to provide
1491 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1492 
1493    Level: beginner
1494 
1495    Notes:
1496    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1497 
1498    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1499    options cannot be mixed without intervening calls to the assembly
1500    routines.
1501 
1502    `MatSetValues()` uses 0-based row and column numbers in Fortran
1503    as well as in C.
1504 
1505    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1506    simply ignored. This allows easily inserting element stiffness matrices
1507    with homogeneous Dirchlet boundary conditions that you don't want represented
1508    in the matrix.
1509 
1510    Efficiency Alert:
1511    The routine `MatSetValuesBlocked()` may offer much better efficiency
1512    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1513 
1514     This is currently not optimized for any particular `ISType`
1515 
1516    Developer Notes:
1517     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1518                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1519 
1520 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1521           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1522 @*/
1523 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1524 {
1525   PetscInt        m, n;
1526   const PetscInt *rows, *cols;
1527 
1528   PetscFunctionBeginHot;
1529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1530   PetscCall(ISGetIndices(ism, &rows));
1531   PetscCall(ISGetIndices(isn, &cols));
1532   PetscCall(ISGetLocalSize(ism, &m));
1533   PetscCall(ISGetLocalSize(isn, &n));
1534   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1535   PetscCall(ISRestoreIndices(ism, &rows));
1536   PetscCall(ISRestoreIndices(isn, &cols));
1537   PetscFunctionReturn(PETSC_SUCCESS);
1538 }
1539 
1540 /*@
1541    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1542         values into a matrix
1543 
1544    Not Collective
1545 
1546    Input Parameters:
1547 +  mat - the matrix
1548 .  row - the (block) row to set
1549 -  v - a logically two-dimensional array of values
1550 
1551    Level: intermediate
1552 
1553    Notes:
1554    The values, `v`, are column-oriented (for the block version) and sorted
1555 
1556    All the nonzeros in the row must be provided
1557 
1558    The matrix must have previously had its column indices set, likely by having been assembled.
1559 
1560    The row must belong to this process
1561 
1562 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1563           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1564 @*/
1565 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1566 {
1567   PetscInt globalrow;
1568 
1569   PetscFunctionBegin;
1570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1571   PetscValidType(mat, 1);
1572   PetscValidScalarPointer(v, 3);
1573   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1574   PetscCall(MatSetValuesRow(mat, globalrow, v));
1575   PetscFunctionReturn(PETSC_SUCCESS);
1576 }
1577 
1578 /*@
1579    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1580         values into a matrix
1581 
1582    Not Collective
1583 
1584    Input Parameters:
1585 +  mat - the matrix
1586 .  row - the (block) row to set
1587 -  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
1588 
1589    Level: advanced
1590 
1591    Notes:
1592    The values, `v`, are column-oriented for the block version.
1593 
1594    All the nonzeros in the row must be provided
1595 
1596    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1597 
1598    The row must belong to this process
1599 
1600 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1601           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1602 @*/
1603 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1604 {
1605   PetscFunctionBeginHot;
1606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1607   PetscValidType(mat, 1);
1608   MatCheckPreallocated(mat, 1);
1609   PetscValidScalarPointer(v, 3);
1610   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1611   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1612   mat->insertmode = INSERT_VALUES;
1613 
1614   if (mat->assembled) {
1615     mat->was_assembled = PETSC_TRUE;
1616     mat->assembled     = PETSC_FALSE;
1617   }
1618   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1619   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1620   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1621   PetscFunctionReturn(PETSC_SUCCESS);
1622 }
1623 
1624 /*@
1625    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1626      Using structured grid indexing
1627 
1628    Not Collective
1629 
1630    Input Parameters:
1631 +  mat - the matrix
1632 .  m - number of rows being entered
1633 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1634 .  n - number of columns being entered
1635 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1636 .  v - a logically two-dimensional array of values
1637 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1638 
1639    Level: beginner
1640 
1641    Notes:
1642    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1643 
1644    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1645    options cannot be mixed without intervening calls to the assembly
1646    routines.
1647 
1648    The grid coordinates are across the entire grid, not just the local portion
1649 
1650    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1651    as well as in C.
1652 
1653    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1654 
1655    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1656    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1657 
1658    The columns and rows in the stencil passed in MUST be contained within the
1659    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1660    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1661    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1662    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1663 
1664    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1665    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1666    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1667    `DM_BOUNDARY_PERIODIC` boundary type.
1668 
1669    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
1670    a single value per point) you can skip filling those indices.
1671 
1672    Inspired by the structured grid interface to the HYPRE package
1673    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1674 
1675    Efficiency Alert:
1676    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1677    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1678 
1679    Fortran Note:
1680    `idxm` and `idxn` should be declared as
1681 $     MatStencil idxm(4,m),idxn(4,n)
1682    and the values inserted using
1683 .vb
1684     idxm(MatStencil_i,1) = i
1685     idxm(MatStencil_j,1) = j
1686     idxm(MatStencil_k,1) = k
1687     idxm(MatStencil_c,1) = c
1688     etc
1689 .ve
1690 
1691 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1692           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1693 @*/
1694 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1695 {
1696   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1697   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1698   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1699 
1700   PetscFunctionBegin;
1701   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1703   PetscValidType(mat, 1);
1704   PetscValidPointer(idxm, 3);
1705   PetscValidPointer(idxn, 5);
1706 
1707   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1708     jdxm = buf;
1709     jdxn = buf + m;
1710   } else {
1711     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1712     jdxm = bufm;
1713     jdxn = bufn;
1714   }
1715   for (i = 0; i < m; i++) {
1716     for (j = 0; j < 3 - sdim; j++) dxm++;
1717     tmp = *dxm++ - starts[0];
1718     for (j = 0; j < dim - 1; j++) {
1719       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1720       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1721     }
1722     if (mat->stencil.noc) dxm++;
1723     jdxm[i] = tmp;
1724   }
1725   for (i = 0; i < n; i++) {
1726     for (j = 0; j < 3 - sdim; j++) dxn++;
1727     tmp = *dxn++ - starts[0];
1728     for (j = 0; j < dim - 1; j++) {
1729       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1730       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1731     }
1732     if (mat->stencil.noc) dxn++;
1733     jdxn[i] = tmp;
1734   }
1735   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1736   PetscCall(PetscFree2(bufm, bufn));
1737   PetscFunctionReturn(PETSC_SUCCESS);
1738 }
1739 
1740 /*@
1741    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1742      Using structured grid indexing
1743 
1744    Not Collective
1745 
1746    Input Parameters:
1747 +  mat - the matrix
1748 .  m - number of rows being entered
1749 .  idxm - grid coordinates for matrix rows being entered
1750 .  n - number of columns being entered
1751 .  idxn - grid coordinates for matrix columns being entered
1752 .  v - a logically two-dimensional array of values
1753 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1754 
1755    Level: beginner
1756 
1757    Notes:
1758    By default the values, `v`, are row-oriented and unsorted.
1759    See `MatSetOption()` for other options.
1760 
1761    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1762    options cannot be mixed without intervening calls to the assembly
1763    routines.
1764 
1765    The grid coordinates are across the entire grid, not just the local portion
1766 
1767    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1768    as well as in C.
1769 
1770    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1771 
1772    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1773    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1774 
1775    The columns and rows in the stencil passed in MUST be contained within the
1776    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1777    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1778    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1779    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1780 
1781    Negative indices may be passed in idxm and idxn, these rows and columns are
1782    simply ignored. This allows easily inserting element stiffness matrices
1783    with homogeneous Dirchlet boundary conditions that you don't want represented
1784    in the matrix.
1785 
1786    Inspired by the structured grid interface to the HYPRE package
1787    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1788 
1789    Fortran Note:
1790    `idxm` and `idxn` should be declared as
1791 $     MatStencil idxm(4,m),idxn(4,n)
1792    and the values inserted using
1793 .vb
1794     idxm(MatStencil_i,1) = i
1795     idxm(MatStencil_j,1) = j
1796     idxm(MatStencil_k,1) = k
1797    etc
1798 .ve
1799 
1800 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1801           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1802           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1803 @*/
1804 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1805 {
1806   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1807   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1808   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1809 
1810   PetscFunctionBegin;
1811   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1812   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1813   PetscValidType(mat, 1);
1814   PetscValidPointer(idxm, 3);
1815   PetscValidPointer(idxn, 5);
1816   PetscValidScalarPointer(v, 6);
1817 
1818   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1819     jdxm = buf;
1820     jdxn = buf + m;
1821   } else {
1822     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1823     jdxm = bufm;
1824     jdxn = bufn;
1825   }
1826   for (i = 0; i < m; i++) {
1827     for (j = 0; j < 3 - sdim; j++) dxm++;
1828     tmp = *dxm++ - starts[0];
1829     for (j = 0; j < sdim - 1; j++) {
1830       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1831       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1832     }
1833     dxm++;
1834     jdxm[i] = tmp;
1835   }
1836   for (i = 0; i < n; i++) {
1837     for (j = 0; j < 3 - sdim; j++) dxn++;
1838     tmp = *dxn++ - starts[0];
1839     for (j = 0; j < sdim - 1; j++) {
1840       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1841       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1842     }
1843     dxn++;
1844     jdxn[i] = tmp;
1845   }
1846   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1847   PetscCall(PetscFree2(bufm, bufn));
1848   PetscFunctionReturn(PETSC_SUCCESS);
1849 }
1850 
1851 /*@
1852    MatSetStencil - Sets the grid information for setting values into a matrix via
1853         `MatSetValuesStencil()`
1854 
1855    Not Collective
1856 
1857    Input Parameters:
1858 +  mat - the matrix
1859 .  dim - dimension of the grid 1, 2, or 3
1860 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1861 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1862 -  dof - number of degrees of freedom per node
1863 
1864    Level: beginner
1865 
1866    Notes:
1867    Inspired by the structured grid interface to the HYPRE package
1868    (www.llnl.gov/CASC/hyper)
1869 
1870    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1871    user.
1872 
1873 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1874           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1875 @*/
1876 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1877 {
1878   PetscFunctionBegin;
1879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1880   PetscValidIntPointer(dims, 3);
1881   PetscValidIntPointer(starts, 4);
1882 
1883   mat->stencil.dim = dim + (dof > 1);
1884   for (PetscInt i = 0; i < dim; i++) {
1885     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1886     mat->stencil.starts[i] = starts[dim - i - 1];
1887   }
1888   mat->stencil.dims[dim]   = dof;
1889   mat->stencil.starts[dim] = 0;
1890   mat->stencil.noc         = (PetscBool)(dof == 1);
1891   PetscFunctionReturn(PETSC_SUCCESS);
1892 }
1893 
1894 /*@C
1895    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1896 
1897    Not Collective
1898 
1899    Input Parameters:
1900 +  mat - the matrix
1901 .  v - a logically two-dimensional array of values
1902 .  m  - the number of block rows
1903 .  idxm - the global block indices
1904 .  n - the number of block columns
1905 .  idxn - the global block indices
1906 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1907 
1908    Level: intermediate
1909 
1910    Notes:
1911    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1912    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1913 
1914    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1915    NOT the total number of rows/columns; for example, if the block size is 2 and
1916    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1917    The values in idxm would be 1 2; that is the first index for each block divided by
1918    the block size.
1919 
1920    You must call `MatSetBlockSize()` when constructing this matrix (before
1921    preallocating it).
1922 
1923    By default the values, `v`, are row-oriented, so the layout of
1924    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1925 
1926    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1927    options cannot be mixed without intervening calls to the assembly
1928    routines.
1929 
1930    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1931    as well as in C.
1932 
1933    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1934    simply ignored. This allows easily inserting element stiffness matrices
1935    with homogeneous Dirchlet boundary conditions that you don't want represented
1936    in the matrix.
1937 
1938    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1939    internal searching must be done to determine where to place the
1940    data in the matrix storage space.  By instead inserting blocks of
1941    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1942    reduced.
1943 
1944    Example:
1945 .vb
1946    Suppose m=n=2 and block size(bs) = 2 The array is
1947 
1948    1  2  | 3  4
1949    5  6  | 7  8
1950    - - - | - - -
1951    9  10 | 11 12
1952    13 14 | 15 16
1953 
1954    v[] should be passed in like
1955    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1956 
1957   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1958    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1959 .ve
1960 
1961 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1962 @*/
1963 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1964 {
1965   PetscFunctionBeginHot;
1966   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1967   PetscValidType(mat, 1);
1968   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1969   PetscValidIntPointer(idxm, 3);
1970   PetscValidIntPointer(idxn, 5);
1971   MatCheckPreallocated(mat, 1);
1972   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1973   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1974   if (PetscDefined(USE_DEBUG)) {
1975     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1976     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1977   }
1978   if (PetscDefined(USE_DEBUG)) {
1979     PetscInt rbs, cbs, M, N, i;
1980     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1981     PetscCall(MatGetSize(mat, &M, &N));
1982     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);
1983     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);
1984   }
1985   if (mat->assembled) {
1986     mat->was_assembled = PETSC_TRUE;
1987     mat->assembled     = PETSC_FALSE;
1988   }
1989   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1990   if (mat->ops->setvaluesblocked) {
1991     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1992   } else {
1993     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1994     PetscInt i, j, bs, cbs;
1995 
1996     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1997     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1998       iidxm = buf;
1999       iidxn = buf + m * bs;
2000     } else {
2001       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2002       iidxm = bufr;
2003       iidxn = bufc;
2004     }
2005     for (i = 0; i < m; i++) {
2006       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2007     }
2008     if (m != n || bs != cbs || idxm != idxn) {
2009       for (i = 0; i < n; i++) {
2010         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2011       }
2012     } else iidxn = iidxm;
2013     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2014     PetscCall(PetscFree2(bufr, bufc));
2015   }
2016   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2017   PetscFunctionReturn(PETSC_SUCCESS);
2018 }
2019 
2020 /*@C
2021    MatGetValues - Gets a block of local values from a matrix.
2022 
2023    Not Collective; can only return values that are owned by the give process
2024 
2025    Input Parameters:
2026 +  mat - the matrix
2027 .  v - a logically two-dimensional array for storing the values
2028 .  m  - the number of rows
2029 .  idxm - the  global indices of the rows
2030 .  n - the number of columns
2031 -  idxn - the global indices of the columns
2032 
2033    Level: advanced
2034 
2035    Notes:
2036      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2037      The values, `v`, are then returned in a row-oriented format,
2038      analogous to that used by default in `MatSetValues()`.
2039 
2040      `MatGetValues()` uses 0-based row and column numbers in
2041      Fortran as well as in C.
2042 
2043      `MatGetValues()` requires that the matrix has been assembled
2044      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2045      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2046      without intermediate matrix assembly.
2047 
2048      Negative row or column indices will be ignored and those locations in `v` will be
2049      left unchanged.
2050 
2051      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2052      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2053      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2054 
2055 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2056 @*/
2057 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2058 {
2059   PetscFunctionBegin;
2060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2061   PetscValidType(mat, 1);
2062   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2063   PetscValidIntPointer(idxm, 3);
2064   PetscValidIntPointer(idxn, 5);
2065   PetscValidScalarPointer(v, 6);
2066   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2067   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2068   MatCheckPreallocated(mat, 1);
2069 
2070   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2071   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2072   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2073   PetscFunctionReturn(PETSC_SUCCESS);
2074 }
2075 
2076 /*@C
2077    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2078      defined previously by `MatSetLocalToGlobalMapping()`
2079 
2080    Not Collective
2081 
2082    Input Parameters:
2083 +  mat - the matrix
2084 .  nrow - number of rows
2085 .  irow - the row local indices
2086 .  ncol - number of columns
2087 -  icol - the column local indices
2088 
2089    Output Parameter:
2090 .  y -  a logically two-dimensional array of values
2091 
2092    Level: advanced
2093 
2094    Notes:
2095      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2096 
2097      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,
2098      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2099      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2100      with `MatSetLocalToGlobalMapping()`.
2101 
2102    Developer Note:
2103       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2104       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2105 
2106 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2107           `MatSetValuesLocal()`, `MatGetValues()`
2108 @*/
2109 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2110 {
2111   PetscFunctionBeginHot;
2112   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2113   PetscValidType(mat, 1);
2114   MatCheckPreallocated(mat, 1);
2115   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2116   PetscValidIntPointer(irow, 3);
2117   PetscValidIntPointer(icol, 5);
2118   if (PetscDefined(USE_DEBUG)) {
2119     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2120     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2121   }
2122   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2123   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2124   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2125   else {
2126     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2127     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2128       irowm = buf;
2129       icolm = buf + nrow;
2130     } else {
2131       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2132       irowm = bufr;
2133       icolm = bufc;
2134     }
2135     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2136     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2137     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2138     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2139     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2140     PetscCall(PetscFree2(bufr, bufc));
2141   }
2142   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2143   PetscFunctionReturn(PETSC_SUCCESS);
2144 }
2145 
2146 /*@
2147   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2148   the same size. Currently, this can only be called once and creates the given matrix.
2149 
2150   Not Collective
2151 
2152   Input Parameters:
2153 + mat - the matrix
2154 . nb - the number of blocks
2155 . bs - the number of rows (and columns) in each block
2156 . rows - a concatenation of the rows for each block
2157 - v - a concatenation of logically two-dimensional arrays of values
2158 
2159   Level: advanced
2160 
2161   Note:
2162   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2163 
2164   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2165 
2166 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2167           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2168 @*/
2169 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2170 {
2171   PetscFunctionBegin;
2172   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2173   PetscValidType(mat, 1);
2174   PetscValidIntPointer(rows, 4);
2175   PetscValidScalarPointer(v, 5);
2176   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2177 
2178   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2179   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2180   else {
2181     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2182   }
2183   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2184   PetscFunctionReturn(PETSC_SUCCESS);
2185 }
2186 
2187 /*@
2188    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2189    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2190    using a local (per-processor) numbering.
2191 
2192    Not Collective
2193 
2194    Input Parameters:
2195 +  x - the matrix
2196 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2197 -  cmapping - column mapping
2198 
2199    Level: intermediate
2200 
2201    Note:
2202    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2203 
2204 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2205 @*/
2206 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2207 {
2208   PetscFunctionBegin;
2209   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2210   PetscValidType(x, 1);
2211   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2212   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2213   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2214   else {
2215     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2216     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2217   }
2218   PetscFunctionReturn(PETSC_SUCCESS);
2219 }
2220 
2221 /*@
2222    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2223 
2224    Not Collective
2225 
2226    Input Parameter:
2227 .  A - the matrix
2228 
2229    Output Parameters:
2230 + rmapping - row mapping
2231 - cmapping - column mapping
2232 
2233    Level: advanced
2234 
2235 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2236 @*/
2237 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2238 {
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2241   PetscValidType(A, 1);
2242   if (rmapping) {
2243     PetscValidPointer(rmapping, 2);
2244     *rmapping = A->rmap->mapping;
2245   }
2246   if (cmapping) {
2247     PetscValidPointer(cmapping, 3);
2248     *cmapping = A->cmap->mapping;
2249   }
2250   PetscFunctionReturn(PETSC_SUCCESS);
2251 }
2252 
2253 /*@
2254    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2255 
2256    Logically Collective
2257 
2258    Input Parameters:
2259 +  A - the matrix
2260 . rmap - row layout
2261 - cmap - column layout
2262 
2263    Level: advanced
2264 
2265    Note:
2266    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2267 
2268 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2269 @*/
2270 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2271 {
2272   PetscFunctionBegin;
2273   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2274   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2275   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2276   PetscFunctionReturn(PETSC_SUCCESS);
2277 }
2278 
2279 /*@
2280    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2281 
2282    Not Collective
2283 
2284    Input Parameter:
2285 .  A - the matrix
2286 
2287    Output Parameters:
2288 + rmap - row layout
2289 - cmap - column layout
2290 
2291    Level: advanced
2292 
2293 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2294 @*/
2295 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2296 {
2297   PetscFunctionBegin;
2298   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2299   PetscValidType(A, 1);
2300   if (rmap) {
2301     PetscValidPointer(rmap, 2);
2302     *rmap = A->rmap;
2303   }
2304   if (cmap) {
2305     PetscValidPointer(cmap, 3);
2306     *cmap = A->cmap;
2307   }
2308   PetscFunctionReturn(PETSC_SUCCESS);
2309 }
2310 
2311 /*@C
2312    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2313    using a local numbering of the nodes.
2314 
2315    Not Collective
2316 
2317    Input Parameters:
2318 +  mat - the matrix
2319 .  nrow - number of rows
2320 .  irow - the row local indices
2321 .  ncol - number of columns
2322 .  icol - the column local indices
2323 .  y -  a logically two-dimensional array of values
2324 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2325 
2326    Level: intermediate
2327 
2328    Notes:
2329    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2330       `MatSetUp()` before using this routine
2331 
2332    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2333 
2334    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2335    options cannot be mixed without intervening calls to the assembly
2336    routines.
2337 
2338    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2339    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2340 
2341    Developer Note:
2342     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2343                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2344 
2345 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2346           `MatGetValuesLocal()`
2347 @*/
2348 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2349 {
2350   PetscFunctionBeginHot;
2351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2352   PetscValidType(mat, 1);
2353   MatCheckPreallocated(mat, 1);
2354   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2355   PetscValidIntPointer(irow, 3);
2356   PetscValidIntPointer(icol, 5);
2357   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2358   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2359   if (PetscDefined(USE_DEBUG)) {
2360     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2361     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2362   }
2363 
2364   if (mat->assembled) {
2365     mat->was_assembled = PETSC_TRUE;
2366     mat->assembled     = PETSC_FALSE;
2367   }
2368   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2369   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2370   else {
2371     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2372     const PetscInt *irowm, *icolm;
2373 
2374     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2375       bufr  = buf;
2376       bufc  = buf + nrow;
2377       irowm = bufr;
2378       icolm = bufc;
2379     } else {
2380       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2381       irowm = bufr;
2382       icolm = bufc;
2383     }
2384     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2385     else irowm = irow;
2386     if (mat->cmap->mapping) {
2387       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2388         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2389       } else icolm = irowm;
2390     } else icolm = icol;
2391     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2392     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2393   }
2394   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2395   PetscFunctionReturn(PETSC_SUCCESS);
2396 }
2397 
2398 /*@C
2399    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2400    using a local ordering of the nodes a block at a time.
2401 
2402    Not Collective
2403 
2404    Input Parameters:
2405 +  x - the matrix
2406 .  nrow - number of rows
2407 .  irow - the row local indices
2408 .  ncol - number of columns
2409 .  icol - the column local indices
2410 .  y -  a logically two-dimensional array of values
2411 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2412 
2413    Level: intermediate
2414 
2415    Notes:
2416    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2417       `MatSetUp()` before using this routine
2418 
2419    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2420       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2421 
2422    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2423    options cannot be mixed without intervening calls to the assembly
2424    routines.
2425 
2426    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2427    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2428 
2429    Developer Note:
2430     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2431                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2432 
2433 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2434           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2435 @*/
2436 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2437 {
2438   PetscFunctionBeginHot;
2439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2440   PetscValidType(mat, 1);
2441   MatCheckPreallocated(mat, 1);
2442   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2443   PetscValidIntPointer(irow, 3);
2444   PetscValidIntPointer(icol, 5);
2445   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2446   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2447   if (PetscDefined(USE_DEBUG)) {
2448     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2449     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);
2450   }
2451 
2452   if (mat->assembled) {
2453     mat->was_assembled = PETSC_TRUE;
2454     mat->assembled     = PETSC_FALSE;
2455   }
2456   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2457     PetscInt irbs, rbs;
2458     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2459     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2460     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2461   }
2462   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2463     PetscInt icbs, cbs;
2464     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2465     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2466     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2467   }
2468   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2469   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2470   else {
2471     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2472     const PetscInt *irowm, *icolm;
2473 
2474     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2475       bufr  = buf;
2476       bufc  = buf + nrow;
2477       irowm = bufr;
2478       icolm = bufc;
2479     } else {
2480       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2481       irowm = bufr;
2482       icolm = bufc;
2483     }
2484     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2485     else irowm = irow;
2486     if (mat->cmap->mapping) {
2487       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2488         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2489       } else icolm = irowm;
2490     } else icolm = icol;
2491     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2492     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2493   }
2494   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2495   PetscFunctionReturn(PETSC_SUCCESS);
2496 }
2497 
2498 /*@
2499    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2500 
2501    Collective
2502 
2503    Input Parameters:
2504 +  mat - the matrix
2505 -  x   - the vector to be multiplied
2506 
2507    Output Parameters:
2508 .  y - the result
2509 
2510    Level: developer
2511 
2512    Note:
2513    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2514    call `MatMultDiagonalBlock`(A,y,y).
2515 
2516 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2517 @*/
2518 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2519 {
2520   PetscFunctionBegin;
2521   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2522   PetscValidType(mat, 1);
2523   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2524   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2525 
2526   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2527   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2528   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2529   MatCheckPreallocated(mat, 1);
2530 
2531   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2532   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2533   PetscFunctionReturn(PETSC_SUCCESS);
2534 }
2535 
2536 /*@
2537    MatMult - Computes the matrix-vector product, y = Ax.
2538 
2539    Neighbor-wise Collective
2540 
2541    Input Parameters:
2542 +  mat - the matrix
2543 -  x   - the vector to be multiplied
2544 
2545    Output Parameters:
2546 .  y - the result
2547 
2548    Level: beginner
2549 
2550    Note:
2551    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2552    call `MatMult`(A,y,y).
2553 
2554 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2555 @*/
2556 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2557 {
2558   PetscFunctionBegin;
2559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2560   PetscValidType(mat, 1);
2561   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2562   VecCheckAssembled(x);
2563   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2564   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2565   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2566   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2567   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);
2568   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);
2569   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);
2570   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);
2571   PetscCall(VecSetErrorIfLocked(y, 3));
2572   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2573   MatCheckPreallocated(mat, 1);
2574 
2575   PetscCall(VecLockReadPush(x));
2576   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2577   PetscUseTypeMethod(mat, mult, x, y);
2578   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2579   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2580   PetscCall(VecLockReadPop(x));
2581   PetscFunctionReturn(PETSC_SUCCESS);
2582 }
2583 
2584 /*@
2585    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2586 
2587    Neighbor-wise Collective
2588 
2589    Input Parameters:
2590 +  mat - the matrix
2591 -  x   - the vector to be multiplied
2592 
2593    Output Parameters:
2594 .  y - the result
2595 
2596    Level: beginner
2597 
2598    Notes:
2599    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2600    call `MatMultTranspose`(A,y,y).
2601 
2602    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2603    use `MatMultHermitianTranspose()`
2604 
2605 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2606 @*/
2607 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2608 {
2609   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2610 
2611   PetscFunctionBegin;
2612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2613   PetscValidType(mat, 1);
2614   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2615   VecCheckAssembled(x);
2616   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2617 
2618   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2619   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2620   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2621   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);
2622   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);
2623   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);
2624   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);
2625   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2626   MatCheckPreallocated(mat, 1);
2627 
2628   if (!mat->ops->multtranspose) {
2629     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2630     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);
2631   } else op = mat->ops->multtranspose;
2632   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2633   PetscCall(VecLockReadPush(x));
2634   PetscCall((*op)(mat, x, y));
2635   PetscCall(VecLockReadPop(x));
2636   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2637   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2638   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2639   PetscFunctionReturn(PETSC_SUCCESS);
2640 }
2641 
2642 /*@
2643    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2644 
2645    Neighbor-wise Collective
2646 
2647    Input Parameters:
2648 +  mat - the matrix
2649 -  x   - the vector to be multilplied
2650 
2651    Output Parameters:
2652 .  y - the result
2653 
2654    Level: beginner
2655 
2656    Notes:
2657    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2658    call `MatMultHermitianTranspose`(A,y,y).
2659 
2660    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2661 
2662    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2663 
2664 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2665 @*/
2666 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2667 {
2668   PetscFunctionBegin;
2669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2670   PetscValidType(mat, 1);
2671   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2672   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2673 
2674   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2675   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2676   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2677   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);
2678   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);
2679   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);
2680   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);
2681   MatCheckPreallocated(mat, 1);
2682 
2683   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2684 #if defined(PETSC_USE_COMPLEX)
2685   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2686     PetscCall(VecLockReadPush(x));
2687     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2688     else PetscUseTypeMethod(mat, mult, x, y);
2689     PetscCall(VecLockReadPop(x));
2690   } else {
2691     Vec w;
2692     PetscCall(VecDuplicate(x, &w));
2693     PetscCall(VecCopy(x, w));
2694     PetscCall(VecConjugate(w));
2695     PetscCall(MatMultTranspose(mat, w, y));
2696     PetscCall(VecDestroy(&w));
2697     PetscCall(VecConjugate(y));
2698   }
2699   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2700 #else
2701   PetscCall(MatMultTranspose(mat, x, y));
2702 #endif
2703   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2704   PetscFunctionReturn(PETSC_SUCCESS);
2705 }
2706 
2707 /*@
2708     MatMultAdd -  Computes v3 = v2 + A * v1.
2709 
2710     Neighbor-wise Collective
2711 
2712     Input Parameters:
2713 +   mat - the matrix
2714 -   v1, v2 - the vectors
2715 
2716     Output Parameters:
2717 .   v3 - the result
2718 
2719     Level: beginner
2720 
2721     Note:
2722     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2723     call `MatMultAdd`(A,v1,v2,v1).
2724 
2725 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2726 @*/
2727 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2728 {
2729   PetscFunctionBegin;
2730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2731   PetscValidType(mat, 1);
2732   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2733   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2734   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2735 
2736   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2737   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2738   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);
2739   /* 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);
2740      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); */
2741   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);
2742   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);
2743   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2744   MatCheckPreallocated(mat, 1);
2745 
2746   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2747   PetscCall(VecLockReadPush(v1));
2748   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2749   PetscCall(VecLockReadPop(v1));
2750   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2751   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2752   PetscFunctionReturn(PETSC_SUCCESS);
2753 }
2754 
2755 /*@
2756    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2757 
2758    Neighbor-wise Collective
2759 
2760    Input Parameters:
2761 +  mat - the matrix
2762 -  v1, v2 - the vectors
2763 
2764    Output Parameters:
2765 .  v3 - the result
2766 
2767    Level: beginner
2768 
2769    Note:
2770    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2771    call `MatMultTransposeAdd`(A,v1,v2,v1).
2772 
2773 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2774 @*/
2775 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2776 {
2777   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2778 
2779   PetscFunctionBegin;
2780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2781   PetscValidType(mat, 1);
2782   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2783   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2784   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2785 
2786   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2787   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2788   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);
2789   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);
2790   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);
2791   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2792   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2793   MatCheckPreallocated(mat, 1);
2794 
2795   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2796   PetscCall(VecLockReadPush(v1));
2797   PetscCall((*op)(mat, v1, v2, v3));
2798   PetscCall(VecLockReadPop(v1));
2799   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2800   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2801   PetscFunctionReturn(PETSC_SUCCESS);
2802 }
2803 
2804 /*@
2805    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2806 
2807    Neighbor-wise Collective
2808 
2809    Input Parameters:
2810 +  mat - the matrix
2811 -  v1, v2 - the vectors
2812 
2813    Output Parameters:
2814 .  v3 - the result
2815 
2816    Level: beginner
2817 
2818    Note:
2819    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2820    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2821 
2822 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2823 @*/
2824 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2825 {
2826   PetscFunctionBegin;
2827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2828   PetscValidType(mat, 1);
2829   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2830   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2831   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2832 
2833   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2834   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2835   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2836   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);
2837   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);
2838   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);
2839   MatCheckPreallocated(mat, 1);
2840 
2841   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2842   PetscCall(VecLockReadPush(v1));
2843   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2844   else {
2845     Vec w, z;
2846     PetscCall(VecDuplicate(v1, &w));
2847     PetscCall(VecCopy(v1, w));
2848     PetscCall(VecConjugate(w));
2849     PetscCall(VecDuplicate(v3, &z));
2850     PetscCall(MatMultTranspose(mat, w, z));
2851     PetscCall(VecDestroy(&w));
2852     PetscCall(VecConjugate(z));
2853     if (v2 != v3) {
2854       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2855     } else {
2856       PetscCall(VecAXPY(v3, 1.0, z));
2857     }
2858     PetscCall(VecDestroy(&z));
2859   }
2860   PetscCall(VecLockReadPop(v1));
2861   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2862   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2863   PetscFunctionReturn(PETSC_SUCCESS);
2864 }
2865 
2866 /*@C
2867    MatGetFactorType - gets the type of factorization it is
2868 
2869    Not Collective
2870 
2871    Input Parameters:
2872 .  mat - the matrix
2873 
2874    Output Parameters:
2875 .  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`
2876 
2877    Level: intermediate
2878 
2879 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2880           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2881 @*/
2882 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2883 {
2884   PetscFunctionBegin;
2885   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2886   PetscValidType(mat, 1);
2887   PetscValidPointer(t, 2);
2888   *t = mat->factortype;
2889   PetscFunctionReturn(PETSC_SUCCESS);
2890 }
2891 
2892 /*@C
2893    MatSetFactorType - sets the type of factorization it is
2894 
2895    Logically Collective
2896 
2897    Input Parameters:
2898 +  mat - the matrix
2899 -  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`
2900 
2901    Level: intermediate
2902 
2903 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2904           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2905 @*/
2906 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2907 {
2908   PetscFunctionBegin;
2909   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2910   PetscValidType(mat, 1);
2911   mat->factortype = t;
2912   PetscFunctionReturn(PETSC_SUCCESS);
2913 }
2914 
2915 /*@C
2916    MatGetInfo - Returns information about matrix storage (number of
2917    nonzeros, memory, etc.).
2918 
2919    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2920 
2921    Input Parameters:
2922 +  mat - the matrix
2923 -  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)
2924 
2925    Output Parameters:
2926 .  info - matrix information context
2927 
2928    Notes:
2929    The `MatInfo` context contains a variety of matrix data, including
2930    number of nonzeros allocated and used, number of mallocs during
2931    matrix assembly, etc.  Additional information for factored matrices
2932    is provided (such as the fill ratio, number of mallocs during
2933    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2934    when using the runtime options
2935 $       -info -mat_view ::ascii_info
2936 
2937    Example:
2938    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2939    data within the MatInfo context.  For example,
2940 .vb
2941       MatInfo info;
2942       Mat     A;
2943       double  mal, nz_a, nz_u;
2944 
2945       MatGetInfo(A,MAT_LOCAL,&info);
2946       mal  = info.mallocs;
2947       nz_a = info.nz_allocated;
2948 .ve
2949 
2950    Fortran users should declare info as a double precision
2951    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2952    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2953    a complete list of parameter names.
2954 .vb
2955       double  precision info(MAT_INFO_SIZE)
2956       double  precision mal, nz_a
2957       Mat     A
2958       integer ierr
2959 
2960       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2961       mal = info(MAT_INFO_MALLOCS)
2962       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2963 .ve
2964 
2965     Level: intermediate
2966 
2967     Developer Note:
2968     The Fortran interface is not autogenerated as the
2969     interface definition cannot be generated correctly [due to `MatInfo` argument]
2970 
2971 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2972 @*/
2973 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2974 {
2975   PetscFunctionBegin;
2976   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2977   PetscValidType(mat, 1);
2978   PetscValidPointer(info, 3);
2979   MatCheckPreallocated(mat, 1);
2980   PetscUseTypeMethod(mat, getinfo, flag, info);
2981   PetscFunctionReturn(PETSC_SUCCESS);
2982 }
2983 
2984 /*
2985    This is used by external packages where it is not easy to get the info from the actual
2986    matrix factorization.
2987 */
2988 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2989 {
2990   PetscFunctionBegin;
2991   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2992   PetscFunctionReturn(PETSC_SUCCESS);
2993 }
2994 
2995 /*@C
2996    MatLUFactor - Performs in-place LU factorization of matrix.
2997 
2998    Collective
2999 
3000    Input Parameters:
3001 +  mat - the matrix
3002 .  row - row permutation
3003 .  col - column permutation
3004 -  info - options for factorization, includes
3005 .vb
3006           fill - expected fill as ratio of original fill.
3007           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3008                    Run with the option -info to determine an optimal value to use
3009 .ve
3010    Level: developer
3011 
3012    Notes:
3013    Most users should employ the `KSP` interface for linear solvers
3014    instead of working directly with matrix algebra routines such as this.
3015    See, e.g., `KSPCreate()`.
3016 
3017    This changes the state of the matrix to a factored matrix; it cannot be used
3018    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3019 
3020    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3021    when not using `KSP`.
3022 
3023    Developer Note:
3024    The Fortran interface is not autogenerated as the
3025    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3026 
3027 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3028           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3029 @*/
3030 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3031 {
3032   MatFactorInfo tinfo;
3033 
3034   PetscFunctionBegin;
3035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3036   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3037   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3038   if (info) PetscValidPointer(info, 4);
3039   PetscValidType(mat, 1);
3040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3041   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3042   MatCheckPreallocated(mat, 1);
3043   if (!info) {
3044     PetscCall(MatFactorInfoInitialize(&tinfo));
3045     info = &tinfo;
3046   }
3047 
3048   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3049   PetscUseTypeMethod(mat, lufactor, row, col, info);
3050   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3051   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3052   PetscFunctionReturn(PETSC_SUCCESS);
3053 }
3054 
3055 /*@C
3056    MatILUFactor - Performs in-place ILU factorization of matrix.
3057 
3058    Collective
3059 
3060    Input Parameters:
3061 +  mat - the matrix
3062 .  row - row permutation
3063 .  col - column permutation
3064 -  info - structure containing
3065 .vb
3066       levels - number of levels of fill.
3067       expected fill - as ratio of original fill.
3068       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3069                 missing diagonal entries)
3070 .ve
3071 
3072    Level: developer
3073 
3074    Notes:
3075    Most users should employ the `KSP` interface for linear solvers
3076    instead of working directly with matrix algebra routines such as this.
3077    See, e.g., `KSPCreate()`.
3078 
3079    Probably really in-place only when level of fill is zero, otherwise allocates
3080    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3081    when not using `KSP`.
3082 
3083    Developer Note:
3084    The Fortran interface is not autogenerated as the
3085    interface definition cannot be generated correctly [due to MatFactorInfo]
3086 
3087 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3088 @*/
3089 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3090 {
3091   PetscFunctionBegin;
3092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3093   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3094   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3095   PetscValidPointer(info, 4);
3096   PetscValidType(mat, 1);
3097   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3098   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3099   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3100   MatCheckPreallocated(mat, 1);
3101 
3102   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3103   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3104   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3105   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3106   PetscFunctionReturn(PETSC_SUCCESS);
3107 }
3108 
3109 /*@C
3110    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3111    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3112 
3113    Collective
3114 
3115    Input Parameters:
3116 +  fact - the factor matrix obtained with `MatGetFactor()`
3117 .  mat - the matrix
3118 .  row, col - row and column permutations
3119 -  info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123 .ve
3124 
3125    Level: developer
3126 
3127    Notes:
3128     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3129 
3130    Most users should employ the simplified `KSP` interface for linear solvers
3131    instead of working directly with matrix algebra routines such as this.
3132    See, e.g., `KSPCreate()`.
3133 
3134    Developer Note:
3135    The Fortran interface is not autogenerated as the
3136    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137 
3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139 @*/
3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141 {
3142   MatFactorInfo tinfo;
3143 
3144   PetscFunctionBegin;
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(mat, 2);
3150   PetscValidPointer(fact, 1);
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   if (!(fact)->ops->lufactorsymbolic) {
3154     MatSolverType stype;
3155     PetscCall(MatFactorGetSolverType(fact, &stype));
3156     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3157   }
3158   MatCheckPreallocated(mat, 2);
3159   if (!info) {
3160     PetscCall(MatFactorInfoInitialize(&tinfo));
3161     info = &tinfo;
3162   }
3163 
3164   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3165   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3166   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3167   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3168   PetscFunctionReturn(PETSC_SUCCESS);
3169 }
3170 
3171 /*@C
3172    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3173    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3174 
3175    Collective
3176 
3177    Input Parameters:
3178 +  fact - the factor matrix obtained with `MatGetFactor()`
3179 .  mat - the matrix
3180 -  info - options for factorization
3181 
3182    Level: developer
3183 
3184    Notes:
3185    See `MatLUFactor()` for in-place factorization.  See
3186    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3187 
3188    Most users should employ the `KSP` interface for linear solvers
3189    instead of working directly with matrix algebra routines such as this.
3190    See, e.g., `KSPCreate()`.
3191 
3192     Developer Note:
3193     The Fortran interface is not autogenerated as the
3194     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3195 
3196 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3197 @*/
3198 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3199 {
3200   MatFactorInfo tinfo;
3201 
3202   PetscFunctionBegin;
3203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3204   PetscValidType(mat, 2);
3205   PetscValidPointer(fact, 1);
3206   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3208   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,
3209              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3210 
3211   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3212   MatCheckPreallocated(mat, 2);
3213   if (!info) {
3214     PetscCall(MatFactorInfoInitialize(&tinfo));
3215     info = &tinfo;
3216   }
3217 
3218   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3219   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3220   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3221   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3222   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3223   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3224   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3225   PetscFunctionReturn(PETSC_SUCCESS);
3226 }
3227 
3228 /*@C
3229    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3230    symmetric matrix.
3231 
3232    Collective
3233 
3234    Input Parameters:
3235 +  mat - the matrix
3236 .  perm - row and column permutations
3237 -  f - expected fill as ratio of original fill
3238 
3239    Level: developer
3240 
3241    Notes:
3242    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3243    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3244 
3245    Most users should employ the `KSP` interface for linear solvers
3246    instead of working directly with matrix algebra routines such as this.
3247    See, e.g., `KSPCreate()`.
3248 
3249    Developer Note:
3250    The Fortran interface is not autogenerated as the
3251    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3252 
3253 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3254           `MatGetOrdering()`
3255 @*/
3256 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3257 {
3258   MatFactorInfo tinfo;
3259 
3260   PetscFunctionBegin;
3261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3262   PetscValidType(mat, 1);
3263   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3264   if (info) PetscValidPointer(info, 3);
3265   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3268   MatCheckPreallocated(mat, 1);
3269   if (!info) {
3270     PetscCall(MatFactorInfoInitialize(&tinfo));
3271     info = &tinfo;
3272   }
3273 
3274   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3275   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3276   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3277   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3278   PetscFunctionReturn(PETSC_SUCCESS);
3279 }
3280 
3281 /*@C
3282    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3283    of a symmetric matrix.
3284 
3285    Collective
3286 
3287    Input Parameters:
3288 +  fact - the factor matrix obtained with `MatGetFactor()`
3289 .  mat - the matrix
3290 .  perm - row and column permutations
3291 -  info - options for factorization, includes
3292 .vb
3293           fill - expected fill as ratio of original fill.
3294           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3295                    Run with the option -info to determine an optimal value to use
3296 .ve
3297 
3298    Level: developer
3299 
3300    Notes:
3301    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3302    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3303 
3304    Most users should employ the `KSP` interface for linear solvers
3305    instead of working directly with matrix algebra routines such as this.
3306    See, e.g., `KSPCreate()`.
3307 
3308    Developer Note:
3309    The Fortran interface is not autogenerated as the
3310    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3311 
3312 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3313           `MatGetOrdering()`
3314 @*/
3315 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3316 {
3317   MatFactorInfo tinfo;
3318 
3319   PetscFunctionBegin;
3320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3321   PetscValidType(mat, 2);
3322   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3323   if (info) PetscValidPointer(info, 4);
3324   PetscValidPointer(fact, 1);
3325   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3326   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3327   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3328   if (!(fact)->ops->choleskyfactorsymbolic) {
3329     MatSolverType stype;
3330     PetscCall(MatFactorGetSolverType(fact, &stype));
3331     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3332   }
3333   MatCheckPreallocated(mat, 2);
3334   if (!info) {
3335     PetscCall(MatFactorInfoInitialize(&tinfo));
3336     info = &tinfo;
3337   }
3338 
3339   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3340   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3341   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3342   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3343   PetscFunctionReturn(PETSC_SUCCESS);
3344 }
3345 
3346 /*@C
3347    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3348    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3349    `MatCholeskyFactorSymbolic()`.
3350 
3351    Collective
3352 
3353    Input Parameters:
3354 +  fact - the factor matrix obtained with `MatGetFactor()`
3355 .  mat - the initial matrix
3356 .  info - options for factorization
3357 -  fact - the symbolic factor of mat
3358 
3359    Level: developer
3360 
3361    Note:
3362    Most users should employ the `KSP` interface for linear solvers
3363    instead of working directly with matrix algebra routines such as this.
3364    See, e.g., `KSPCreate()`.
3365 
3366    Developer Note:
3367    The Fortran interface is not autogenerated as the
3368    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3369 
3370 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3371 @*/
3372 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3373 {
3374   MatFactorInfo tinfo;
3375 
3376   PetscFunctionBegin;
3377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3378   PetscValidType(mat, 2);
3379   PetscValidPointer(fact, 1);
3380   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3381   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3382   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3383   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,
3384              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3385   MatCheckPreallocated(mat, 2);
3386   if (!info) {
3387     PetscCall(MatFactorInfoInitialize(&tinfo));
3388     info = &tinfo;
3389   }
3390 
3391   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3392   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3393   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3394   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3395   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3396   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3397   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3398   PetscFunctionReturn(PETSC_SUCCESS);
3399 }
3400 
3401 /*@
3402    MatQRFactor - Performs in-place QR factorization of matrix.
3403 
3404    Collective
3405 
3406    Input Parameters:
3407 +  mat - the matrix
3408 .  col - column permutation
3409 -  info - options for factorization, includes
3410 .vb
3411           fill - expected fill as ratio of original fill.
3412           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3413                    Run with the option -info to determine an optimal value to use
3414 .ve
3415 
3416    Level: developer
3417 
3418    Notes:
3419    Most users should employ the `KSP` interface for linear solvers
3420    instead of working directly with matrix algebra routines such as this.
3421    See, e.g., `KSPCreate()`.
3422 
3423    This changes the state of the matrix to a factored matrix; it cannot be used
3424    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3425 
3426    Developer Note:
3427    The Fortran interface is not autogenerated as the
3428    interface definition cannot be generated correctly [due to MatFactorInfo]
3429 
3430 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3431           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3432 @*/
3433 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3434 {
3435   PetscFunctionBegin;
3436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3437   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3438   if (info) PetscValidPointer(info, 3);
3439   PetscValidType(mat, 1);
3440   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3441   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3442   MatCheckPreallocated(mat, 1);
3443   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3444   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3445   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3446   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3447   PetscFunctionReturn(PETSC_SUCCESS);
3448 }
3449 
3450 /*@
3451    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3452    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3453 
3454    Collective
3455 
3456    Input Parameters:
3457 +  fact - the factor matrix obtained with `MatGetFactor()`
3458 .  mat - the matrix
3459 .  col - column permutation
3460 -  info - options for factorization, includes
3461 .vb
3462           fill - expected fill as ratio of original fill.
3463           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3464                    Run with the option -info to determine an optimal value to use
3465 .ve
3466 
3467    Level: developer
3468 
3469    Note:
3470    Most users should employ the `KSP` interface for linear solvers
3471    instead of working directly with matrix algebra routines such as this.
3472    See, e.g., `KSPCreate()`.
3473 
3474    Developer Note:
3475    The Fortran interface is not autogenerated as the
3476    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3477 
3478 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3479 @*/
3480 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3481 {
3482   MatFactorInfo tinfo;
3483 
3484   PetscFunctionBegin;
3485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3486   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3487   if (info) PetscValidPointer(info, 4);
3488   PetscValidType(mat, 2);
3489   PetscValidPointer(fact, 1);
3490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3492   MatCheckPreallocated(mat, 2);
3493   if (!info) {
3494     PetscCall(MatFactorInfoInitialize(&tinfo));
3495     info = &tinfo;
3496   }
3497 
3498   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3499   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3500   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3501   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3502   PetscFunctionReturn(PETSC_SUCCESS);
3503 }
3504 
3505 /*@
3506    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3507    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3508 
3509    Collective
3510 
3511    Input Parameters:
3512 +  fact - the factor matrix obtained with `MatGetFactor()`
3513 .  mat - the matrix
3514 -  info - options for factorization
3515 
3516    Level: developer
3517 
3518    Notes:
3519    See `MatQRFactor()` for in-place factorization.
3520 
3521    Most users should employ the `KSP` interface for linear solvers
3522    instead of working directly with matrix algebra routines such as this.
3523    See, e.g., `KSPCreate()`.
3524 
3525    Developer Note:
3526    The Fortran interface is not autogenerated as the
3527    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3528 
3529 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3530 @*/
3531 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3532 {
3533   MatFactorInfo tinfo;
3534 
3535   PetscFunctionBegin;
3536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3537   PetscValidType(mat, 2);
3538   PetscValidPointer(fact, 1);
3539   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3540   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3541   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,
3542              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3543 
3544   MatCheckPreallocated(mat, 2);
3545   if (!info) {
3546     PetscCall(MatFactorInfoInitialize(&tinfo));
3547     info = &tinfo;
3548   }
3549 
3550   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3551   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3552   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3553   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3554   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3555   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3556   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3557   PetscFunctionReturn(PETSC_SUCCESS);
3558 }
3559 
3560 /*@
3561    MatSolve - Solves A x = b, given a factored matrix.
3562 
3563    Neighbor-wise Collective
3564 
3565    Input Parameters:
3566 +  mat - the factored matrix
3567 -  b - the right-hand-side vector
3568 
3569    Output Parameter:
3570 .  x - the result vector
3571 
3572    Level: developer
3573 
3574    Notes:
3575    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3576    call `MatSolve`(A,x,x).
3577 
3578    Most users should employ the `KSP` interface for linear solvers
3579    instead of working directly with matrix algebra routines such as this.
3580    See, e.g., `KSPCreate()`.
3581 
3582 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3583 @*/
3584 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3585 {
3586   PetscFunctionBegin;
3587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3588   PetscValidType(mat, 1);
3589   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3590   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3591   PetscCheckSameComm(mat, 1, b, 2);
3592   PetscCheckSameComm(mat, 1, x, 3);
3593   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3594   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);
3595   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);
3596   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);
3597   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3598   MatCheckPreallocated(mat, 1);
3599 
3600   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3601   if (mat->factorerrortype) {
3602     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3603     PetscCall(VecSetInf(x));
3604   } else PetscUseTypeMethod(mat, solve, b, x);
3605   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3606   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3607   PetscFunctionReturn(PETSC_SUCCESS);
3608 }
3609 
3610 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3611 {
3612   Vec      b, x;
3613   PetscInt N, i;
3614   PetscErrorCode (*f)(Mat, Vec, Vec);
3615   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3616 
3617   PetscFunctionBegin;
3618   if (A->factorerrortype) {
3619     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3620     PetscCall(MatSetInf(X));
3621     PetscFunctionReturn(PETSC_SUCCESS);
3622   }
3623   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3624   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3625   PetscCall(MatBoundToCPU(A, &Abound));
3626   if (!Abound) {
3627     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3628     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3629   }
3630 #if defined(PETSC_HAVE_CUDA)
3631   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3632   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3633 #elif (PETSC_HAVE_HIP)
3634   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3635   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3636 #endif
3637   PetscCall(MatGetSize(B, NULL, &N));
3638   for (i = 0; i < N; i++) {
3639     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3640     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3641     PetscCall((*f)(A, b, x));
3642     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3643     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3644   }
3645   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3646   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3647   PetscFunctionReturn(PETSC_SUCCESS);
3648 }
3649 
3650 /*@
3651    MatMatSolve - Solves A X = B, given a factored matrix.
3652 
3653    Neighbor-wise Collective
3654 
3655    Input Parameters:
3656 +  A - the factored matrix
3657 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3658 
3659    Output Parameter:
3660 .  X - the result matrix (dense matrix)
3661 
3662    Level: developer
3663 
3664    Note:
3665    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3666    otherwise, `B` and `X` cannot be the same.
3667 
3668 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3669 @*/
3670 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3671 {
3672   PetscFunctionBegin;
3673   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3674   PetscValidType(A, 1);
3675   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3676   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3677   PetscCheckSameComm(A, 1, B, 2);
3678   PetscCheckSameComm(A, 1, X, 3);
3679   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);
3680   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);
3681   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");
3682   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3683   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3684   MatCheckPreallocated(A, 1);
3685 
3686   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3687   if (!A->ops->matsolve) {
3688     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3689     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3690   } else PetscUseTypeMethod(A, matsolve, B, X);
3691   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3692   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3693   PetscFunctionReturn(PETSC_SUCCESS);
3694 }
3695 
3696 /*@
3697    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3698 
3699    Neighbor-wise Collective
3700 
3701    Input Parameters:
3702 +  A - the factored matrix
3703 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3704 
3705    Output Parameter:
3706 .  X - the result matrix (dense matrix)
3707 
3708    Level: developer
3709 
3710    Note:
3711    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3712    call `MatMatSolveTranspose`(A,X,X).
3713 
3714 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3715 @*/
3716 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3717 {
3718   PetscFunctionBegin;
3719   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3720   PetscValidType(A, 1);
3721   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3722   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3723   PetscCheckSameComm(A, 1, B, 2);
3724   PetscCheckSameComm(A, 1, X, 3);
3725   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3726   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);
3727   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);
3728   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);
3729   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");
3730   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3731   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3732   MatCheckPreallocated(A, 1);
3733 
3734   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3735   if (!A->ops->matsolvetranspose) {
3736     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3737     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3738   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3739   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3740   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3741   PetscFunctionReturn(PETSC_SUCCESS);
3742 }
3743 
3744 /*@
3745    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3746 
3747    Neighbor-wise Collective
3748 
3749    Input Parameters:
3750 +  A - the factored matrix
3751 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3752 
3753    Output Parameter:
3754 .  X - the result matrix (dense matrix)
3755 
3756    Level: developer
3757 
3758    Note:
3759    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
3760    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3761 
3762 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3763 @*/
3764 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3765 {
3766   PetscFunctionBegin;
3767   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3768   PetscValidType(A, 1);
3769   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3770   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3771   PetscCheckSameComm(A, 1, Bt, 2);
3772   PetscCheckSameComm(A, 1, X, 3);
3773 
3774   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3775   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);
3776   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);
3777   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");
3778   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3779   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3780   MatCheckPreallocated(A, 1);
3781 
3782   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3783   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3784   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3785   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3786   PetscFunctionReturn(PETSC_SUCCESS);
3787 }
3788 
3789 /*@
3790    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3791                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3792 
3793    Neighbor-wise Collective
3794 
3795    Input Parameters:
3796 +  mat - the factored matrix
3797 -  b - the right-hand-side vector
3798 
3799    Output Parameter:
3800 .  x - the result vector
3801 
3802    Level: developer
3803 
3804    Notes:
3805    `MatSolve()` should be used for most applications, as it performs
3806    a forward solve followed by a backward solve.
3807 
3808    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3809    call `MatForwardSolve`(A,x,x).
3810 
3811    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3812    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3813    `MatForwardSolve()` solves U^T*D y = b, and
3814    `MatBackwardSolve()` solves U x = y.
3815    Thus they do not provide a symmetric preconditioner.
3816 
3817 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3818 @*/
3819 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3820 {
3821   PetscFunctionBegin;
3822   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3823   PetscValidType(mat, 1);
3824   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3825   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3826   PetscCheckSameComm(mat, 1, b, 2);
3827   PetscCheckSameComm(mat, 1, x, 3);
3828   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3829   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);
3830   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);
3831   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);
3832   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3833   MatCheckPreallocated(mat, 1);
3834 
3835   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3836   PetscUseTypeMethod(mat, forwardsolve, b, x);
3837   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3838   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3839   PetscFunctionReturn(PETSC_SUCCESS);
3840 }
3841 
3842 /*@
3843    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3844                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3845 
3846    Neighbor-wise Collective
3847 
3848    Input Parameters:
3849 +  mat - the factored matrix
3850 -  b - the right-hand-side vector
3851 
3852    Output Parameter:
3853 .  x - the result vector
3854 
3855    Level: developer
3856 
3857    Notes:
3858    `MatSolve()` should be used for most applications, as it performs
3859    a forward solve followed by a backward solve.
3860 
3861    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3862    call `MatBackwardSolve`(A,x,x).
3863 
3864    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3865    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3866    `MatForwardSolve()` solves U^T*D y = b, and
3867    `MatBackwardSolve()` solves U x = y.
3868    Thus they do not provide a symmetric preconditioner.
3869 
3870 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3871 @*/
3872 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3873 {
3874   PetscFunctionBegin;
3875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3876   PetscValidType(mat, 1);
3877   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3878   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3879   PetscCheckSameComm(mat, 1, b, 2);
3880   PetscCheckSameComm(mat, 1, x, 3);
3881   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3882   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);
3883   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);
3884   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);
3885   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3886   MatCheckPreallocated(mat, 1);
3887 
3888   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3889   PetscUseTypeMethod(mat, backwardsolve, b, x);
3890   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3891   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3892   PetscFunctionReturn(PETSC_SUCCESS);
3893 }
3894 
3895 /*@
3896    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3897 
3898    Neighbor-wise Collective
3899 
3900    Input Parameters:
3901 +  mat - the factored matrix
3902 .  b - the right-hand-side vector
3903 -  y - the vector to be added to
3904 
3905    Output Parameter:
3906 .  x - the result vector
3907 
3908    Level: developer
3909 
3910    Note:
3911    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3912    call `MatSolveAdd`(A,x,y,x).
3913 
3914 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3915 @*/
3916 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3917 {
3918   PetscScalar one = 1.0;
3919   Vec         tmp;
3920 
3921   PetscFunctionBegin;
3922   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3923   PetscValidType(mat, 1);
3924   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3925   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3926   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3927   PetscCheckSameComm(mat, 1, b, 2);
3928   PetscCheckSameComm(mat, 1, y, 3);
3929   PetscCheckSameComm(mat, 1, x, 4);
3930   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3931   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);
3932   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);
3933   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);
3934   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);
3935   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);
3936   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3937   MatCheckPreallocated(mat, 1);
3938 
3939   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3940   if (mat->factorerrortype) {
3941     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3942     PetscCall(VecSetInf(x));
3943   } else if (mat->ops->solveadd) {
3944     PetscUseTypeMethod(mat, solveadd, b, y, x);
3945   } else {
3946     /* do the solve then the add manually */
3947     if (x != y) {
3948       PetscCall(MatSolve(mat, b, x));
3949       PetscCall(VecAXPY(x, one, y));
3950     } else {
3951       PetscCall(VecDuplicate(x, &tmp));
3952       PetscCall(VecCopy(x, tmp));
3953       PetscCall(MatSolve(mat, b, x));
3954       PetscCall(VecAXPY(x, one, tmp));
3955       PetscCall(VecDestroy(&tmp));
3956     }
3957   }
3958   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3959   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3960   PetscFunctionReturn(PETSC_SUCCESS);
3961 }
3962 
3963 /*@
3964    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3965 
3966    Neighbor-wise Collective
3967 
3968    Input Parameters:
3969 +  mat - the factored matrix
3970 -  b - the right-hand-side vector
3971 
3972    Output Parameter:
3973 .  x - the result vector
3974 
3975    Level: developer
3976 
3977    Notes:
3978    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3979    call `MatSolveTranspose`(A,x,x).
3980 
3981    Most users should employ the `KSP` interface for linear solvers
3982    instead of working directly with matrix algebra routines such as this.
3983    See, e.g., `KSPCreate()`.
3984 
3985 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3986 @*/
3987 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3988 {
3989   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3990 
3991   PetscFunctionBegin;
3992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3993   PetscValidType(mat, 1);
3994   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3995   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3996   PetscCheckSameComm(mat, 1, b, 2);
3997   PetscCheckSameComm(mat, 1, x, 3);
3998   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3999   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);
4000   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);
4001   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4002   MatCheckPreallocated(mat, 1);
4003   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4004   if (mat->factorerrortype) {
4005     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4006     PetscCall(VecSetInf(x));
4007   } else {
4008     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4009     PetscCall((*f)(mat, b, x));
4010   }
4011   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4012   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4013   PetscFunctionReturn(PETSC_SUCCESS);
4014 }
4015 
4016 /*@
4017    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4018                       factored matrix.
4019 
4020    Neighbor-wise Collective
4021 
4022    Input Parameters:
4023 +  mat - the factored matrix
4024 .  b - the right-hand-side vector
4025 -  y - the vector to be added to
4026 
4027    Output Parameter:
4028 .  x - the result vector
4029 
4030    Level: developer
4031 
4032    Note:
4033    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4034    call `MatSolveTransposeAdd`(A,x,y,x).
4035 
4036 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4037 @*/
4038 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4039 {
4040   PetscScalar one = 1.0;
4041   Vec         tmp;
4042   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4043 
4044   PetscFunctionBegin;
4045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4046   PetscValidType(mat, 1);
4047   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4048   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4049   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4050   PetscCheckSameComm(mat, 1, b, 2);
4051   PetscCheckSameComm(mat, 1, y, 3);
4052   PetscCheckSameComm(mat, 1, x, 4);
4053   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4054   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);
4055   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);
4056   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);
4057   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);
4058   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4059   MatCheckPreallocated(mat, 1);
4060 
4061   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4062   if (mat->factorerrortype) {
4063     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4064     PetscCall(VecSetInf(x));
4065   } else if (f) {
4066     PetscCall((*f)(mat, b, y, x));
4067   } else {
4068     /* do the solve then the add manually */
4069     if (x != y) {
4070       PetscCall(MatSolveTranspose(mat, b, x));
4071       PetscCall(VecAXPY(x, one, y));
4072     } else {
4073       PetscCall(VecDuplicate(x, &tmp));
4074       PetscCall(VecCopy(x, tmp));
4075       PetscCall(MatSolveTranspose(mat, b, x));
4076       PetscCall(VecAXPY(x, one, tmp));
4077       PetscCall(VecDestroy(&tmp));
4078     }
4079   }
4080   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4081   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4082   PetscFunctionReturn(PETSC_SUCCESS);
4083 }
4084 
4085 /*@
4086    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4087 
4088    Neighbor-wise Collective
4089 
4090    Input Parameters:
4091 +  mat - the matrix
4092 .  b - the right hand side
4093 .  omega - the relaxation factor
4094 .  flag - flag indicating the type of SOR (see below)
4095 .  shift -  diagonal shift
4096 .  its - the number of iterations
4097 -  lits - the number of local iterations
4098 
4099    Output Parameter:
4100 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4101 
4102    SOR Flags:
4103 +     `SOR_FORWARD_SWEEP` - forward SOR
4104 .     `SOR_BACKWARD_SWEEP` - backward SOR
4105 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4106 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4107 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4108 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4109 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4110 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4111          upper/lower triangular part of matrix to
4112          vector (with omega)
4113 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4114 
4115    Level: developer
4116 
4117    Notes:
4118    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4119    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4120    on each processor.
4121 
4122    Application programmers will not generally use `MatSOR()` directly,
4123    but instead will employ the `KSP`/`PC` interface.
4124 
4125    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4126 
4127    Most users should employ the `KSP` interface for linear solvers
4128    instead of working directly with matrix algebra routines such as this.
4129    See, e.g., `KSPCreate()`.
4130 
4131    Vectors `x` and `b` CANNOT be the same
4132 
4133    The flags are implemented as bitwise inclusive or operations.
4134    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4135    to specify a zero initial guess for SSOR.
4136 
4137    Developer Note:
4138    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4139 
4140 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4141 @*/
4142 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4143 {
4144   PetscFunctionBegin;
4145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4146   PetscValidType(mat, 1);
4147   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4148   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4149   PetscCheckSameComm(mat, 1, b, 2);
4150   PetscCheckSameComm(mat, 1, x, 8);
4151   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4153   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);
4154   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);
4155   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);
4156   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4157   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4158   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4159 
4160   MatCheckPreallocated(mat, 1);
4161   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4162   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4163   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4164   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4165   PetscFunctionReturn(PETSC_SUCCESS);
4166 }
4167 
4168 /*
4169       Default matrix copy routine.
4170 */
4171 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4172 {
4173   PetscInt           i, rstart = 0, rend = 0, nz;
4174   const PetscInt    *cwork;
4175   const PetscScalar *vwork;
4176 
4177   PetscFunctionBegin;
4178   if (B->assembled) PetscCall(MatZeroEntries(B));
4179   if (str == SAME_NONZERO_PATTERN) {
4180     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4181     for (i = rstart; i < rend; i++) {
4182       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4183       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4184       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4185     }
4186   } else {
4187     PetscCall(MatAYPX(B, 0.0, A, str));
4188   }
4189   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4190   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4191   PetscFunctionReturn(PETSC_SUCCESS);
4192 }
4193 
4194 /*@
4195    MatCopy - Copies a matrix to another matrix.
4196 
4197    Collective
4198 
4199    Input Parameters:
4200 +  A - the matrix
4201 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4202 
4203    Output Parameter:
4204 .  B - where the copy is put
4205 
4206    Level: intermediate
4207 
4208    Notes:
4209    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4210 
4211    `MatCopy()` copies the matrix entries of a matrix to another existing
4212    matrix (after first zeroing the second matrix).  A related routine is
4213    `MatConvert()`, which first creates a new matrix and then copies the data.
4214 
4215 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4216 @*/
4217 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4218 {
4219   PetscInt i;
4220 
4221   PetscFunctionBegin;
4222   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4223   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4224   PetscValidType(A, 1);
4225   PetscValidType(B, 2);
4226   PetscCheckSameComm(A, 1, B, 2);
4227   MatCheckPreallocated(B, 2);
4228   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4229   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4230   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,
4231              A->cmap->N, B->cmap->N);
4232   MatCheckPreallocated(A, 1);
4233   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4234 
4235   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4236   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4237   else PetscCall(MatCopy_Basic(A, B, str));
4238 
4239   B->stencil.dim = A->stencil.dim;
4240   B->stencil.noc = A->stencil.noc;
4241   for (i = 0; i <= A->stencil.dim; i++) {
4242     B->stencil.dims[i]   = A->stencil.dims[i];
4243     B->stencil.starts[i] = A->stencil.starts[i];
4244   }
4245 
4246   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4247   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4248   PetscFunctionReturn(PETSC_SUCCESS);
4249 }
4250 
4251 /*@C
4252    MatConvert - Converts a matrix to another matrix, either of the same
4253    or different type.
4254 
4255    Collective
4256 
4257    Input Parameters:
4258 +  mat - the matrix
4259 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4260    same type as the original matrix.
4261 -  reuse - denotes if the destination matrix is to be created or reused.
4262    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
4263    `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).
4264 
4265    Output Parameter:
4266 .  M - pointer to place new matrix
4267 
4268    Level: intermediate
4269 
4270    Notes:
4271    `MatConvert()` first creates a new matrix and then copies the data from
4272    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4273    entries of one matrix to another already existing matrix context.
4274 
4275    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4276    the MPI communicator of the generated matrix is always the same as the communicator
4277    of the input matrix.
4278 
4279 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4280 @*/
4281 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4282 {
4283   PetscBool  sametype, issame, flg;
4284   PetscBool3 issymmetric, ishermitian;
4285   char       convname[256], mtype[256];
4286   Mat        B;
4287 
4288   PetscFunctionBegin;
4289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4290   PetscValidType(mat, 1);
4291   PetscValidPointer(M, 4);
4292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4293   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4294   MatCheckPreallocated(mat, 1);
4295 
4296   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4297   if (flg) newtype = mtype;
4298 
4299   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4300   PetscCall(PetscStrcmp(newtype, "same", &issame));
4301   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4302   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");
4303 
4304   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4305     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4306     PetscFunctionReturn(PETSC_SUCCESS);
4307   }
4308 
4309   /* Cache Mat options because some converters use MatHeaderReplace  */
4310   issymmetric = mat->symmetric;
4311   ishermitian = mat->hermitian;
4312 
4313   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4314     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4315     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4316   } else {
4317     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4318     const char *prefix[3]                                 = {"seq", "mpi", ""};
4319     PetscInt    i;
4320     /*
4321        Order of precedence:
4322        0) See if newtype is a superclass of the current matrix.
4323        1) See if a specialized converter is known to the current matrix.
4324        2) See if a specialized converter is known to the desired matrix class.
4325        3) See if a good general converter is registered for the desired class
4326           (as of 6/27/03 only MATMPIADJ falls into this category).
4327        4) See if a good general converter is known for the current matrix.
4328        5) Use a really basic converter.
4329     */
4330 
4331     /* 0) See if newtype is a superclass of the current matrix.
4332           i.e mat is mpiaij and newtype is aij */
4333     for (i = 0; i < 2; i++) {
4334       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4335       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4336       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4337       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4338       if (flg) {
4339         if (reuse == MAT_INPLACE_MATRIX) {
4340           PetscCall(PetscInfo(mat, "Early return\n"));
4341           PetscFunctionReturn(PETSC_SUCCESS);
4342         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4343           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4344           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4345           PetscFunctionReturn(PETSC_SUCCESS);
4346         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4347           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4348           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4349           PetscFunctionReturn(PETSC_SUCCESS);
4350         }
4351       }
4352     }
4353     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4354     for (i = 0; i < 3; i++) {
4355       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4357       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4358       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4361       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4362       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4363       if (conv) goto foundconv;
4364     }
4365 
4366     /* 2)  See if a specialized converter is known to the desired matrix class. */
4367     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4368     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4369     PetscCall(MatSetType(B, newtype));
4370     for (i = 0; i < 3; i++) {
4371       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4372       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4377       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4378       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4379       if (conv) {
4380         PetscCall(MatDestroy(&B));
4381         goto foundconv;
4382       }
4383     }
4384 
4385     /* 3) See if a good general converter is registered for the desired class */
4386     conv = B->ops->convertfrom;
4387     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4388     PetscCall(MatDestroy(&B));
4389     if (conv) goto foundconv;
4390 
4391     /* 4) See if a good general converter is known for the current matrix */
4392     if (mat->ops->convert) conv = mat->ops->convert;
4393     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4394     if (conv) goto foundconv;
4395 
4396     /* 5) Use a really basic converter. */
4397     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4398     conv = MatConvert_Basic;
4399 
4400   foundconv:
4401     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4402     PetscCall((*conv)(mat, newtype, reuse, M));
4403     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4404       /* the block sizes must be same if the mappings are copied over */
4405       (*M)->rmap->bs = mat->rmap->bs;
4406       (*M)->cmap->bs = mat->cmap->bs;
4407       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4408       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4409       (*M)->rmap->mapping = mat->rmap->mapping;
4410       (*M)->cmap->mapping = mat->cmap->mapping;
4411     }
4412     (*M)->stencil.dim = mat->stencil.dim;
4413     (*M)->stencil.noc = mat->stencil.noc;
4414     for (i = 0; i <= mat->stencil.dim; i++) {
4415       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4416       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4417     }
4418     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4419   }
4420   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4421 
4422   /* Copy Mat options */
4423   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4424   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4425   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4426   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4427   PetscFunctionReturn(PETSC_SUCCESS);
4428 }
4429 
4430 /*@C
4431    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4432 
4433    Not Collective
4434 
4435    Input Parameter:
4436 .  mat - the matrix, must be a factored matrix
4437 
4438    Output Parameter:
4439 .   type - the string name of the package (do not free this string)
4440 
4441    Level: intermediate
4442 
4443    Fortran Note:
4444    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4445 
4446 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4447 @*/
4448 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4449 {
4450   PetscErrorCode (*conv)(Mat, MatSolverType *);
4451 
4452   PetscFunctionBegin;
4453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4454   PetscValidType(mat, 1);
4455   PetscValidPointer(type, 2);
4456   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4457   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4458   if (conv) PetscCall((*conv)(mat, type));
4459   else *type = MATSOLVERPETSC;
4460   PetscFunctionReturn(PETSC_SUCCESS);
4461 }
4462 
4463 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4464 struct _MatSolverTypeForSpecifcType {
4465   MatType mtype;
4466   /* no entry for MAT_FACTOR_NONE */
4467   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4468   MatSolverTypeForSpecifcType next;
4469 };
4470 
4471 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4472 struct _MatSolverTypeHolder {
4473   char                       *name;
4474   MatSolverTypeForSpecifcType handlers;
4475   MatSolverTypeHolder         next;
4476 };
4477 
4478 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4479 
4480 /*@C
4481    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4482 
4483    Input Parameters:
4484 +    package - name of the package, for example petsc or superlu
4485 .    mtype - the matrix type that works with this package
4486 .    ftype - the type of factorization supported by the package
4487 -    createfactor - routine that will create the factored matrix ready to be used
4488 
4489     Level: developer
4490 
4491 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4492 @*/
4493 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4494 {
4495   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4496   PetscBool                   flg;
4497   MatSolverTypeForSpecifcType inext, iprev = NULL;
4498 
4499   PetscFunctionBegin;
4500   PetscCall(MatInitializePackage());
4501   if (!next) {
4502     PetscCall(PetscNew(&MatSolverTypeHolders));
4503     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4504     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4505     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4506     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4507     PetscFunctionReturn(PETSC_SUCCESS);
4508   }
4509   while (next) {
4510     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4511     if (flg) {
4512       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4513       inext = next->handlers;
4514       while (inext) {
4515         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4516         if (flg) {
4517           inext->createfactor[(int)ftype - 1] = createfactor;
4518           PetscFunctionReturn(PETSC_SUCCESS);
4519         }
4520         iprev = inext;
4521         inext = inext->next;
4522       }
4523       PetscCall(PetscNew(&iprev->next));
4524       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4525       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4526       PetscFunctionReturn(PETSC_SUCCESS);
4527     }
4528     prev = next;
4529     next = next->next;
4530   }
4531   PetscCall(PetscNew(&prev->next));
4532   PetscCall(PetscStrallocpy(package, &prev->next->name));
4533   PetscCall(PetscNew(&prev->next->handlers));
4534   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4535   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4536   PetscFunctionReturn(PETSC_SUCCESS);
4537 }
4538 
4539 /*@C
4540    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4541 
4542    Input Parameters:
4543 +    type - name of the package, for example petsc or superlu
4544 .    ftype - the type of factorization supported by the type
4545 -    mtype - the matrix type that works with this type
4546 
4547    Output Parameters:
4548 +   foundtype - `PETSC_TRUE` if the type was registered
4549 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4550 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4551 
4552     Level: developer
4553 
4554 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4555 @*/
4556 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4557 {
4558   MatSolverTypeHolder         next = MatSolverTypeHolders;
4559   PetscBool                   flg;
4560   MatSolverTypeForSpecifcType inext;
4561 
4562   PetscFunctionBegin;
4563   if (foundtype) *foundtype = PETSC_FALSE;
4564   if (foundmtype) *foundmtype = PETSC_FALSE;
4565   if (createfactor) *createfactor = NULL;
4566 
4567   if (type) {
4568     while (next) {
4569       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4570       if (flg) {
4571         if (foundtype) *foundtype = PETSC_TRUE;
4572         inext = next->handlers;
4573         while (inext) {
4574           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4575           if (flg) {
4576             if (foundmtype) *foundmtype = PETSC_TRUE;
4577             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4578             PetscFunctionReturn(PETSC_SUCCESS);
4579           }
4580           inext = inext->next;
4581         }
4582       }
4583       next = next->next;
4584     }
4585   } else {
4586     while (next) {
4587       inext = next->handlers;
4588       while (inext) {
4589         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4590         if (flg && inext->createfactor[(int)ftype - 1]) {
4591           if (foundtype) *foundtype = PETSC_TRUE;
4592           if (foundmtype) *foundmtype = PETSC_TRUE;
4593           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4594           PetscFunctionReturn(PETSC_SUCCESS);
4595         }
4596         inext = inext->next;
4597       }
4598       next = next->next;
4599     }
4600     /* try with base classes inext->mtype */
4601     next = MatSolverTypeHolders;
4602     while (next) {
4603       inext = next->handlers;
4604       while (inext) {
4605         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4606         if (flg && inext->createfactor[(int)ftype - 1]) {
4607           if (foundtype) *foundtype = PETSC_TRUE;
4608           if (foundmtype) *foundmtype = PETSC_TRUE;
4609           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4610           PetscFunctionReturn(PETSC_SUCCESS);
4611         }
4612         inext = inext->next;
4613       }
4614       next = next->next;
4615     }
4616   }
4617   PetscFunctionReturn(PETSC_SUCCESS);
4618 }
4619 
4620 PetscErrorCode MatSolverTypeDestroy(void)
4621 {
4622   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4623   MatSolverTypeForSpecifcType inext, iprev;
4624 
4625   PetscFunctionBegin;
4626   while (next) {
4627     PetscCall(PetscFree(next->name));
4628     inext = next->handlers;
4629     while (inext) {
4630       PetscCall(PetscFree(inext->mtype));
4631       iprev = inext;
4632       inext = inext->next;
4633       PetscCall(PetscFree(iprev));
4634     }
4635     prev = next;
4636     next = next->next;
4637     PetscCall(PetscFree(prev));
4638   }
4639   MatSolverTypeHolders = NULL;
4640   PetscFunctionReturn(PETSC_SUCCESS);
4641 }
4642 
4643 /*@C
4644    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4645 
4646    Logically Collective
4647 
4648    Input Parameters:
4649 .  mat - the matrix
4650 
4651    Output Parameters:
4652 .  flg - `PETSC_TRUE` if uses the ordering
4653 
4654    Level: developer
4655 
4656    Note:
4657    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4658    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4659 
4660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4661 @*/
4662 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4663 {
4664   PetscFunctionBegin;
4665   *flg = mat->canuseordering;
4666   PetscFunctionReturn(PETSC_SUCCESS);
4667 }
4668 
4669 /*@C
4670    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4671 
4672    Logically Collective
4673 
4674    Input Parameters:
4675 .  mat - the matrix obtained with `MatGetFactor()`
4676 
4677    Output Parameters:
4678 .  otype - the preferred type
4679 
4680    Level: developer
4681 
4682 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4683 @*/
4684 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4685 {
4686   PetscFunctionBegin;
4687   *otype = mat->preferredordering[ftype];
4688   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4689   PetscFunctionReturn(PETSC_SUCCESS);
4690 }
4691 
4692 /*@C
4693    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4694 
4695    Collective
4696 
4697    Input Parameters:
4698 +  mat - the matrix
4699 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4700 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4701 
4702    Output Parameters:
4703 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4704 
4705    Options Database Key:
4706 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4707                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4708 
4709    Level: intermediate
4710 
4711    Notes:
4712      Users usually access the factorization solvers via `KSP`
4713 
4714       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4715      such as pastix, superlu, mumps etc.
4716 
4717       PETSc must have been ./configure to use the external solver, using the option --download-package
4718 
4719       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4720       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4721       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4722 
4723    Developer Note:
4724       This should actually be called `MatCreateFactor()` since it creates a new factor object
4725 
4726 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4727           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4728 @*/
4729 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4730 {
4731   PetscBool foundtype, foundmtype;
4732   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4733 
4734   PetscFunctionBegin;
4735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4736   PetscValidType(mat, 1);
4737 
4738   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4739   MatCheckPreallocated(mat, 1);
4740 
4741   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4742   if (!foundtype) {
4743     if (type) {
4744       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],
4745               ((PetscObject)mat)->type_name, type);
4746     } else {
4747       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);
4748     }
4749   }
4750   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4751   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);
4752 
4753   PetscCall((*conv)(mat, ftype, f));
4754   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4755   PetscFunctionReturn(PETSC_SUCCESS);
4756 }
4757 
4758 /*@C
4759    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4760 
4761    Not Collective
4762 
4763    Input Parameters:
4764 +  mat - the matrix
4765 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4766 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4767 
4768    Output Parameter:
4769 .    flg - PETSC_TRUE if the factorization is available
4770 
4771    Level: intermediate
4772 
4773    Notes:
4774       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4775      such as pastix, superlu, mumps etc.
4776 
4777       PETSc must have been ./configure to use the external solver, using the option --download-package
4778 
4779    Developer Note:
4780       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4781 
4782 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4783           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4784 @*/
4785 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4786 {
4787   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4788 
4789   PetscFunctionBegin;
4790   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4791   PetscValidType(mat, 1);
4792   PetscValidBoolPointer(flg, 4);
4793 
4794   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4795   MatCheckPreallocated(mat, 1);
4796 
4797   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4798   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4799   PetscFunctionReturn(PETSC_SUCCESS);
4800 }
4801 
4802 /*@
4803    MatDuplicate - Duplicates a matrix including the non-zero structure.
4804 
4805    Collective
4806 
4807    Input Parameters:
4808 +  mat - the matrix
4809 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4810         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4811 
4812    Output Parameter:
4813 .  M - pointer to place new matrix
4814 
4815    Level: intermediate
4816 
4817    Notes:
4818     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4819 
4820     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.
4821 
4822     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
4823     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4824     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4825 
4826 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4827 @*/
4828 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4829 {
4830   Mat         B;
4831   VecType     vtype;
4832   PetscInt    i;
4833   PetscObject dm;
4834   void (*viewf)(void);
4835 
4836   PetscFunctionBegin;
4837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4838   PetscValidType(mat, 1);
4839   PetscValidPointer(M, 3);
4840   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4841   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4842   MatCheckPreallocated(mat, 1);
4843 
4844   *M = NULL;
4845   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4846   PetscUseTypeMethod(mat, duplicate, op, M);
4847   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4848   B = *M;
4849 
4850   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4851   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4852   PetscCall(MatGetVecType(mat, &vtype));
4853   PetscCall(MatSetVecType(B, vtype));
4854 
4855   B->stencil.dim = mat->stencil.dim;
4856   B->stencil.noc = mat->stencil.noc;
4857   for (i = 0; i <= mat->stencil.dim; i++) {
4858     B->stencil.dims[i]   = mat->stencil.dims[i];
4859     B->stencil.starts[i] = mat->stencil.starts[i];
4860   }
4861 
4862   B->nooffproczerorows = mat->nooffproczerorows;
4863   B->nooffprocentries  = mat->nooffprocentries;
4864 
4865   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4866   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4867   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4868   PetscFunctionReturn(PETSC_SUCCESS);
4869 }
4870 
4871 /*@
4872    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4873 
4874    Logically Collective
4875 
4876    Input Parameters:
4877 +  mat - the matrix
4878 -  v - the vector for storing the diagonal
4879 
4880    Output Parameter:
4881 .  v - the diagonal of the matrix
4882 
4883    Level: intermediate
4884 
4885    Note:
4886    Currently only correct in parallel for square matrices.
4887 
4888 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4889 @*/
4890 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4891 {
4892   PetscFunctionBegin;
4893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4894   PetscValidType(mat, 1);
4895   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4896   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4897   MatCheckPreallocated(mat, 1);
4898 
4899   PetscUseTypeMethod(mat, getdiagonal, v);
4900   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4901   PetscFunctionReturn(PETSC_SUCCESS);
4902 }
4903 
4904 /*@C
4905    MatGetRowMin - Gets the minimum value (of the real part) of each
4906         row of the matrix
4907 
4908    Logically Collective
4909 
4910    Input Parameter:
4911 .  mat - the matrix
4912 
4913    Output Parameters:
4914 +  v - the vector for storing the maximums
4915 -  idx - the indices of the column found for each row (optional)
4916 
4917    Level: intermediate
4918 
4919    Note:
4920     The result of this call are the same as if one converted the matrix to dense format
4921       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4922 
4923     This code is only implemented for a couple of matrix formats.
4924 
4925 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4926           `MatGetRowMax()`
4927 @*/
4928 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4929 {
4930   PetscFunctionBegin;
4931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4932   PetscValidType(mat, 1);
4933   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4934   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4935 
4936   if (!mat->cmap->N) {
4937     PetscCall(VecSet(v, PETSC_MAX_REAL));
4938     if (idx) {
4939       PetscInt i, m = mat->rmap->n;
4940       for (i = 0; i < m; i++) idx[i] = -1;
4941     }
4942   } else {
4943     MatCheckPreallocated(mat, 1);
4944   }
4945   PetscUseTypeMethod(mat, getrowmin, v, idx);
4946   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4947   PetscFunctionReturn(PETSC_SUCCESS);
4948 }
4949 
4950 /*@C
4951    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4952         row of the matrix
4953 
4954    Logically Collective
4955 
4956    Input Parameter:
4957 .  mat - the matrix
4958 
4959    Output Parameters:
4960 +  v - the vector for storing the minimums
4961 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4962 
4963    Level: intermediate
4964 
4965    Notes:
4966     if a row is completely empty or has only 0.0 values then the idx[] value for that
4967     row is 0 (the first column).
4968 
4969     This code is only implemented for a couple of matrix formats.
4970 
4971 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4972 @*/
4973 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4974 {
4975   PetscFunctionBegin;
4976   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4977   PetscValidType(mat, 1);
4978   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4979   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4980   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4981 
4982   if (!mat->cmap->N) {
4983     PetscCall(VecSet(v, 0.0));
4984     if (idx) {
4985       PetscInt i, m = mat->rmap->n;
4986       for (i = 0; i < m; i++) idx[i] = -1;
4987     }
4988   } else {
4989     MatCheckPreallocated(mat, 1);
4990     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4991     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4992   }
4993   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4994   PetscFunctionReturn(PETSC_SUCCESS);
4995 }
4996 
4997 /*@C
4998    MatGetRowMax - Gets the maximum value (of the real part) of each
4999         row of the matrix
5000 
5001    Logically Collective
5002 
5003    Input Parameter:
5004 .  mat - the matrix
5005 
5006    Output Parameters:
5007 +  v - the vector for storing the maximums
5008 -  idx - the indices of the column found for each row (optional)
5009 
5010    Level: intermediate
5011 
5012    Notes:
5013     The result of this call are the same as if one converted the matrix to dense format
5014       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5015 
5016     This code is only implemented for a couple of matrix formats.
5017 
5018 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5019 @*/
5020 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5021 {
5022   PetscFunctionBegin;
5023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5024   PetscValidType(mat, 1);
5025   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5026   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5027 
5028   if (!mat->cmap->N) {
5029     PetscCall(VecSet(v, PETSC_MIN_REAL));
5030     if (idx) {
5031       PetscInt i, m = mat->rmap->n;
5032       for (i = 0; i < m; i++) idx[i] = -1;
5033     }
5034   } else {
5035     MatCheckPreallocated(mat, 1);
5036     PetscUseTypeMethod(mat, getrowmax, v, idx);
5037   }
5038   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5039   PetscFunctionReturn(PETSC_SUCCESS);
5040 }
5041 
5042 /*@C
5043    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5044         row of the matrix
5045 
5046    Logically Collective
5047 
5048    Input Parameter:
5049 .  mat - the matrix
5050 
5051    Output Parameters:
5052 +  v - the vector for storing the maximums
5053 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5054 
5055    Level: intermediate
5056 
5057    Notes:
5058     if a row is completely empty or has only 0.0 values then the idx[] value for that
5059     row is 0 (the first column).
5060 
5061     This code is only implemented for a couple of matrix formats.
5062 
5063 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5064 @*/
5065 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5066 {
5067   PetscFunctionBegin;
5068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5069   PetscValidType(mat, 1);
5070   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5071   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5072 
5073   if (!mat->cmap->N) {
5074     PetscCall(VecSet(v, 0.0));
5075     if (idx) {
5076       PetscInt i, m = mat->rmap->n;
5077       for (i = 0; i < m; i++) idx[i] = -1;
5078     }
5079   } else {
5080     MatCheckPreallocated(mat, 1);
5081     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5082     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5083   }
5084   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5085   PetscFunctionReturn(PETSC_SUCCESS);
5086 }
5087 
5088 /*@
5089    MatGetRowSum - Gets the sum of each row of the matrix
5090 
5091    Logically or Neighborhood Collective
5092 
5093    Input Parameters:
5094 .  mat - the matrix
5095 
5096    Output Parameter:
5097 .  v - the vector for storing the sum of rows
5098 
5099    Level: intermediate
5100 
5101    Notes:
5102     This code is slow since it is not currently specialized for different formats
5103 
5104 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5105 @*/
5106 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5107 {
5108   Vec ones;
5109 
5110   PetscFunctionBegin;
5111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5112   PetscValidType(mat, 1);
5113   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5114   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5115   MatCheckPreallocated(mat, 1);
5116   PetscCall(MatCreateVecs(mat, &ones, NULL));
5117   PetscCall(VecSet(ones, 1.));
5118   PetscCall(MatMult(mat, ones, v));
5119   PetscCall(VecDestroy(&ones));
5120   PetscFunctionReturn(PETSC_SUCCESS);
5121 }
5122 
5123 /*@
5124    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5125    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5126 
5127    Collective
5128 
5129    Input Parameter:
5130 .  mat - the matrix to provide the transpose
5131 
5132    Output Parameter:
5133 .  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
5134 
5135    Level: advanced
5136 
5137    Note:
5138    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
5139    routine allows bypassing that call.
5140 
5141 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5142 @*/
5143 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5144 {
5145   PetscContainer  rB = NULL;
5146   MatParentState *rb = NULL;
5147 
5148   PetscFunctionBegin;
5149   PetscCall(PetscNew(&rb));
5150   rb->id    = ((PetscObject)mat)->id;
5151   rb->state = 0;
5152   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5153   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5154   PetscCall(PetscContainerSetPointer(rB, rb));
5155   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5156   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5157   PetscCall(PetscObjectDereference((PetscObject)rB));
5158   PetscFunctionReturn(PETSC_SUCCESS);
5159 }
5160 
5161 /*@
5162    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5163 
5164    Collective
5165 
5166    Input Parameters:
5167 +  mat - the matrix to transpose
5168 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5169 
5170    Output Parameter:
5171 .  B - the transpose
5172 
5173    Level: intermediate
5174 
5175    Notes:
5176      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5177 
5178      `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
5179      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5180 
5181      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.
5182 
5183      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5184 
5185      If mat is unchanged from the last call this function returns immediately without recomputing the result
5186 
5187      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5188 
5189 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5190           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5191 @*/
5192 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5193 {
5194   PetscContainer  rB = NULL;
5195   MatParentState *rb = NULL;
5196 
5197   PetscFunctionBegin;
5198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5199   PetscValidType(mat, 1);
5200   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5201   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5202   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5203   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5204   MatCheckPreallocated(mat, 1);
5205   if (reuse == MAT_REUSE_MATRIX) {
5206     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5207     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5208     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5209     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5210     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5211   }
5212 
5213   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5214   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5215     PetscUseTypeMethod(mat, transpose, reuse, B);
5216     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5217   }
5218   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5219 
5220   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5221   if (reuse != MAT_INPLACE_MATRIX) {
5222     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5223     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5224     rb->state        = ((PetscObject)mat)->state;
5225     rb->nonzerostate = mat->nonzerostate;
5226   }
5227   PetscFunctionReturn(PETSC_SUCCESS);
5228 }
5229 
5230 /*@
5231    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5232 
5233    Collective
5234 
5235    Input Parameters:
5236 .  A - the matrix to transpose
5237 
5238    Output Parameter:
5239 .  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
5240       numerical portion.
5241 
5242    Level: intermediate
5243 
5244    Note:
5245    This is not supported for many matrix types, use `MatTranspose()` in those cases
5246 
5247 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5248 @*/
5249 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5250 {
5251   PetscFunctionBegin;
5252   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5253   PetscValidType(A, 1);
5254   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5255   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5256   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5257   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5258   PetscCall((*A->ops->transposesymbolic)(A, B));
5259   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5260 
5261   PetscCall(MatTransposeSetPrecursor(A, *B));
5262   PetscFunctionReturn(PETSC_SUCCESS);
5263 }
5264 
5265 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5266 {
5267   PetscContainer  rB;
5268   MatParentState *rb;
5269 
5270   PetscFunctionBegin;
5271   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5272   PetscValidType(A, 1);
5273   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5274   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5275   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5276   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5277   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5278   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5279   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5280   PetscFunctionReturn(PETSC_SUCCESS);
5281 }
5282 
5283 /*@
5284    MatIsTranspose - Test whether a matrix is another one's transpose,
5285         or its own, in which case it tests symmetry.
5286 
5287    Collective
5288 
5289    Input Parameters:
5290 +  A - the matrix to test
5291 -  B - the matrix to test against, this can equal the first parameter
5292 
5293    Output Parameters:
5294 .  flg - the result
5295 
5296    Level: intermediate
5297 
5298    Notes:
5299    Only available for `MATAIJ` matrices.
5300 
5301    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5302    test involves parallel copies of the block-offdiagonal parts of the matrix.
5303 
5304 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5305 @*/
5306 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5307 {
5308   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5309 
5310   PetscFunctionBegin;
5311   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5312   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5313   PetscValidBoolPointer(flg, 4);
5314   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5315   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5316   *flg = PETSC_FALSE;
5317   if (f && g) {
5318     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5319     PetscCall((*f)(A, B, tol, flg));
5320   } else {
5321     MatType mattype;
5322 
5323     PetscCall(MatGetType(f ? B : A, &mattype));
5324     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5325   }
5326   PetscFunctionReturn(PETSC_SUCCESS);
5327 }
5328 
5329 /*@
5330    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5331 
5332    Collective
5333 
5334    Input Parameters:
5335 +  mat - the matrix to transpose and complex conjugate
5336 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5337 
5338    Output Parameter:
5339 .  B - the Hermitian transpose
5340 
5341    Level: intermediate
5342 
5343 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5344 @*/
5345 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5346 {
5347   PetscFunctionBegin;
5348   PetscCall(MatTranspose(mat, reuse, B));
5349 #if defined(PETSC_USE_COMPLEX)
5350   PetscCall(MatConjugate(*B));
5351 #endif
5352   PetscFunctionReturn(PETSC_SUCCESS);
5353 }
5354 
5355 /*@
5356    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5357 
5358    Collective
5359 
5360    Input Parameters:
5361 +  A - the matrix to test
5362 -  B - the matrix to test against, this can equal the first parameter
5363 
5364    Output Parameters:
5365 .  flg - the result
5366 
5367    Level: intermediate
5368 
5369    Notes:
5370    Only available for `MATAIJ` matrices.
5371 
5372    The sequential algorithm
5373    has a running time of the order of the number of nonzeros; the parallel
5374    test involves parallel copies of the block-offdiagonal parts of the matrix.
5375 
5376 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5377 @*/
5378 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5379 {
5380   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5381 
5382   PetscFunctionBegin;
5383   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5384   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5385   PetscValidBoolPointer(flg, 4);
5386   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5387   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5388   if (f && g) {
5389     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5390     PetscCall((*f)(A, B, tol, flg));
5391   }
5392   PetscFunctionReturn(PETSC_SUCCESS);
5393 }
5394 
5395 /*@
5396    MatPermute - Creates a new matrix with rows and columns permuted from the
5397    original.
5398 
5399    Collective
5400 
5401    Input Parameters:
5402 +  mat - the matrix to permute
5403 .  row - row permutation, each processor supplies only the permutation for its rows
5404 -  col - column permutation, each processor supplies only the permutation for its columns
5405 
5406    Output Parameters:
5407 .  B - the permuted matrix
5408 
5409    Level: advanced
5410 
5411    Note:
5412    The index sets map from row/col of permuted matrix to row/col of original matrix.
5413    The index sets should be on the same communicator as mat and have the same local sizes.
5414 
5415    Developer Note:
5416      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5417      exploit the fact that row and col are permutations, consider implementing the
5418      more general `MatCreateSubMatrix()` instead.
5419 
5420 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5421 @*/
5422 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5423 {
5424   PetscFunctionBegin;
5425   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5426   PetscValidType(mat, 1);
5427   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5428   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5429   PetscValidPointer(B, 4);
5430   PetscCheckSameComm(mat, 1, row, 2);
5431   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5432   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5433   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5434   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5435   MatCheckPreallocated(mat, 1);
5436 
5437   if (mat->ops->permute) {
5438     PetscUseTypeMethod(mat, permute, row, col, B);
5439     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5440   } else {
5441     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5442   }
5443   PetscFunctionReturn(PETSC_SUCCESS);
5444 }
5445 
5446 /*@
5447    MatEqual - Compares two matrices.
5448 
5449    Collective
5450 
5451    Input Parameters:
5452 +  A - the first matrix
5453 -  B - the second matrix
5454 
5455    Output Parameter:
5456 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5457 
5458    Level: intermediate
5459 
5460 .seealso: [](chapter_matrices), `Mat`
5461 @*/
5462 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5463 {
5464   PetscFunctionBegin;
5465   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5466   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5467   PetscValidType(A, 1);
5468   PetscValidType(B, 2);
5469   PetscValidBoolPointer(flg, 3);
5470   PetscCheckSameComm(A, 1, B, 2);
5471   MatCheckPreallocated(A, 1);
5472   MatCheckPreallocated(B, 2);
5473   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5474   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475   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,
5476              B->cmap->N);
5477   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5478     PetscUseTypeMethod(A, equal, B, flg);
5479   } else {
5480     PetscCall(MatMultEqual(A, B, 10, flg));
5481   }
5482   PetscFunctionReturn(PETSC_SUCCESS);
5483 }
5484 
5485 /*@
5486    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5487    matrices that are stored as vectors.  Either of the two scaling
5488    matrices can be `NULL`.
5489 
5490    Collective
5491 
5492    Input Parameters:
5493 +  mat - the matrix to be scaled
5494 .  l - the left scaling vector (or `NULL`)
5495 -  r - the right scaling vector (or `NULL`)
5496 
5497    Level: intermediate
5498 
5499    Note:
5500    `MatDiagonalScale()` computes A = LAR, where
5501    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5502    The L scales the rows of the matrix, the R scales the columns of the matrix.
5503 
5504 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5505 @*/
5506 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5507 {
5508   PetscFunctionBegin;
5509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5510   PetscValidType(mat, 1);
5511   if (l) {
5512     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5513     PetscCheckSameComm(mat, 1, l, 2);
5514   }
5515   if (r) {
5516     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5517     PetscCheckSameComm(mat, 1, r, 3);
5518   }
5519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5520   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5521   MatCheckPreallocated(mat, 1);
5522   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5523 
5524   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5525   PetscUseTypeMethod(mat, diagonalscale, l, r);
5526   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5527   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5528   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5529   PetscFunctionReturn(PETSC_SUCCESS);
5530 }
5531 
5532 /*@
5533     MatScale - Scales all elements of a matrix by a given number.
5534 
5535     Logically Collective
5536 
5537     Input Parameters:
5538 +   mat - the matrix to be scaled
5539 -   a  - the scaling value
5540 
5541     Output Parameter:
5542 .   mat - the scaled matrix
5543 
5544     Level: intermediate
5545 
5546 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5547 @*/
5548 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5549 {
5550   PetscFunctionBegin;
5551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5552   PetscValidType(mat, 1);
5553   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5554   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5555   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5556   PetscValidLogicalCollectiveScalar(mat, a, 2);
5557   MatCheckPreallocated(mat, 1);
5558 
5559   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5560   if (a != (PetscScalar)1.0) {
5561     PetscUseTypeMethod(mat, scale, a);
5562     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5563   }
5564   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5565   PetscFunctionReturn(PETSC_SUCCESS);
5566 }
5567 
5568 /*@
5569    MatNorm - Calculates various norms of a matrix.
5570 
5571    Collective
5572 
5573    Input Parameters:
5574 +  mat - the matrix
5575 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5576 
5577    Output Parameter:
5578 .  nrm - the resulting norm
5579 
5580    Level: intermediate
5581 
5582 .seealso: [](chapter_matrices), `Mat`
5583 @*/
5584 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5585 {
5586   PetscFunctionBegin;
5587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5588   PetscValidType(mat, 1);
5589   PetscValidRealPointer(nrm, 3);
5590 
5591   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5592   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5593   MatCheckPreallocated(mat, 1);
5594 
5595   PetscUseTypeMethod(mat, norm, type, nrm);
5596   PetscFunctionReturn(PETSC_SUCCESS);
5597 }
5598 
5599 /*
5600      This variable is used to prevent counting of MatAssemblyBegin() that
5601    are called from within a MatAssemblyEnd().
5602 */
5603 static PetscInt MatAssemblyEnd_InUse = 0;
5604 /*@
5605    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5606    be called after completing all calls to `MatSetValues()`.
5607 
5608    Collective
5609 
5610    Input Parameters:
5611 +  mat - the matrix
5612 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5613 
5614    Level: beginner
5615 
5616    Notes:
5617    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5618    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5619 
5620    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5621    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5622    using the matrix.
5623 
5624    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5625    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
5626    a global collective operation requiring all processes that share the matrix.
5627 
5628    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5629    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5630    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5631 
5632 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5633 @*/
5634 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5635 {
5636   PetscFunctionBegin;
5637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5638   PetscValidType(mat, 1);
5639   MatCheckPreallocated(mat, 1);
5640   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5641   if (mat->assembled) {
5642     mat->was_assembled = PETSC_TRUE;
5643     mat->assembled     = PETSC_FALSE;
5644   }
5645 
5646   if (!MatAssemblyEnd_InUse) {
5647     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5648     PetscTryTypeMethod(mat, assemblybegin, type);
5649     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5650   } else PetscTryTypeMethod(mat, assemblybegin, type);
5651   PetscFunctionReturn(PETSC_SUCCESS);
5652 }
5653 
5654 /*@
5655    MatAssembled - Indicates if a matrix has been assembled and is ready for
5656      use; for example, in matrix-vector product.
5657 
5658    Not Collective
5659 
5660    Input Parameter:
5661 .  mat - the matrix
5662 
5663    Output Parameter:
5664 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5665 
5666    Level: advanced
5667 
5668 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5669 @*/
5670 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5671 {
5672   PetscFunctionBegin;
5673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5674   PetscValidBoolPointer(assembled, 2);
5675   *assembled = mat->assembled;
5676   PetscFunctionReturn(PETSC_SUCCESS);
5677 }
5678 
5679 /*@
5680    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5681    be called after `MatAssemblyBegin()`.
5682 
5683    Collective
5684 
5685    Input Parameters:
5686 +  mat - the matrix
5687 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5688 
5689    Options Database Keys:
5690 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5691 .  -mat_view ::ascii_info_detail - Prints more detailed info
5692 .  -mat_view - Prints matrix in ASCII format
5693 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5694 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5695 .  -display <name> - Sets display name (default is host)
5696 .  -draw_pause <sec> - Sets number of seconds to pause after display
5697 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5698 .  -viewer_socket_machine <machine> - Machine to use for socket
5699 .  -viewer_socket_port <port> - Port number to use for socket
5700 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5701 
5702    Level: beginner
5703 
5704 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5705 @*/
5706 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5707 {
5708   static PetscInt inassm = 0;
5709   PetscBool       flg    = PETSC_FALSE;
5710 
5711   PetscFunctionBegin;
5712   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5713   PetscValidType(mat, 1);
5714 
5715   inassm++;
5716   MatAssemblyEnd_InUse++;
5717   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5718     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5719     PetscTryTypeMethod(mat, assemblyend, type);
5720     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5721   } else PetscTryTypeMethod(mat, assemblyend, type);
5722 
5723   /* Flush assembly is not a true assembly */
5724   if (type != MAT_FLUSH_ASSEMBLY) {
5725     if (mat->num_ass) {
5726       if (!mat->symmetry_eternal) {
5727         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5728         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5729       }
5730       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5731       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5732     }
5733     mat->num_ass++;
5734     mat->assembled        = PETSC_TRUE;
5735     mat->ass_nonzerostate = mat->nonzerostate;
5736   }
5737 
5738   mat->insertmode = NOT_SET_VALUES;
5739   MatAssemblyEnd_InUse--;
5740   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5741   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5742     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5743 
5744     if (mat->checksymmetryonassembly) {
5745       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5746       if (flg) {
5747         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5748       } else {
5749         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5750       }
5751     }
5752     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5753   }
5754   inassm--;
5755   PetscFunctionReturn(PETSC_SUCCESS);
5756 }
5757 
5758 /*@
5759    MatSetOption - Sets a parameter option for a matrix. Some options
5760    may be specific to certain storage formats.  Some options
5761    determine how values will be inserted (or added). Sorted,
5762    row-oriented input will generally assemble the fastest. The default
5763    is row-oriented.
5764 
5765    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5766 
5767    Input Parameters:
5768 +  mat - the matrix
5769 .  option - the option, one of those listed below (and possibly others),
5770 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5771 
5772   Options Describing Matrix Structure:
5773 +    `MAT_SPD` - symmetric positive definite
5774 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5775 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5776 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5777 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5778 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5779 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5780 
5781    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5782    do not need to be computed (usually at a high cost)
5783 
5784    Options For Use with `MatSetValues()`:
5785    Insert a logically dense subblock, which can be
5786 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5787 
5788    These options reflect the data you pass in with `MatSetValues()`; it has
5789    nothing to do with how the data is stored internally in the matrix
5790    data structure.
5791 
5792    When (re)assembling a matrix, we can restrict the input for
5793    efficiency/debugging purposes.  These options include
5794 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5795 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5796 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5797 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5798 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5799 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5800         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5801         performance for very large process counts.
5802 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5803         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5804         functions, instead sending only neighbor messages.
5805 
5806    Level: intermediate
5807 
5808    Notes:
5809    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5810 
5811    Some options are relevant only for particular matrix types and
5812    are thus ignored by others.  Other options are not supported by
5813    certain matrix types and will generate an error message if set.
5814 
5815    If using Fortran to compute a matrix, one may need to
5816    use the column-oriented option (or convert to the row-oriented
5817    format).
5818 
5819    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5820    that would generate a new entry in the nonzero structure is instead
5821    ignored.  Thus, if memory has not already been allocated for this particular
5822    data, then the insertion is ignored. For dense matrices, in which
5823    the entire array is allocated, no entries are ever ignored.
5824    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5825 
5826    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5827    that would generate a new entry in the nonzero structure instead produces
5828    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
5829 
5830    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5831    that would generate a new entry that has not been preallocated will
5832    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5833    only.) This is a useful flag when debugging matrix memory preallocation.
5834    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5835 
5836    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5837    other processors should be dropped, rather than stashed.
5838    This is useful if you know that the "owning" processor is also
5839    always generating the correct matrix entries, so that PETSc need
5840    not transfer duplicate entries generated on another processor.
5841 
5842    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5843    searches during matrix assembly. When this flag is set, the hash table
5844    is created during the first matrix assembly. This hash table is
5845    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5846    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5847    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5848    supported by `MATMPIBAIJ` format only.
5849 
5850    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5851    are kept in the nonzero structure
5852 
5853    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5854    a zero location in the matrix
5855 
5856    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5857 
5858    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5859         zero row routines and thus improves performance for very large process counts.
5860 
5861    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5862         part of the matrix (since they should match the upper triangular part).
5863 
5864    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5865                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5866                      with finite difference schemes with non-periodic boundary conditions.
5867 
5868    Developer Note:
5869    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5870    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5871    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5872    not changed.
5873 
5874 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5875 @*/
5876 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5877 {
5878   PetscFunctionBegin;
5879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5880   if (op > 0) {
5881     PetscValidLogicalCollectiveEnum(mat, op, 2);
5882     PetscValidLogicalCollectiveBool(mat, flg, 3);
5883   }
5884 
5885   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);
5886 
5887   switch (op) {
5888   case MAT_FORCE_DIAGONAL_ENTRIES:
5889     mat->force_diagonals = flg;
5890     PetscFunctionReturn(PETSC_SUCCESS);
5891   case MAT_NO_OFF_PROC_ENTRIES:
5892     mat->nooffprocentries = flg;
5893     PetscFunctionReturn(PETSC_SUCCESS);
5894   case MAT_SUBSET_OFF_PROC_ENTRIES:
5895     mat->assembly_subset = flg;
5896     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5897 #if !defined(PETSC_HAVE_MPIUNI)
5898       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5899 #endif
5900       mat->stash.first_assembly_done = PETSC_FALSE;
5901     }
5902     PetscFunctionReturn(PETSC_SUCCESS);
5903   case MAT_NO_OFF_PROC_ZERO_ROWS:
5904     mat->nooffproczerorows = flg;
5905     PetscFunctionReturn(PETSC_SUCCESS);
5906   case MAT_SPD:
5907     if (flg) {
5908       mat->spd                    = PETSC_BOOL3_TRUE;
5909       mat->symmetric              = PETSC_BOOL3_TRUE;
5910       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5911     } else {
5912       mat->spd = PETSC_BOOL3_FALSE;
5913     }
5914     break;
5915   case MAT_SYMMETRIC:
5916     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5917     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5918 #if !defined(PETSC_USE_COMPLEX)
5919     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5920 #endif
5921     break;
5922   case MAT_HERMITIAN:
5923     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5924     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5925 #if !defined(PETSC_USE_COMPLEX)
5926     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5927 #endif
5928     break;
5929   case MAT_STRUCTURALLY_SYMMETRIC:
5930     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5931     break;
5932   case MAT_SYMMETRY_ETERNAL:
5933     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");
5934     mat->symmetry_eternal = flg;
5935     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5936     break;
5937   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5938     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");
5939     mat->structural_symmetry_eternal = flg;
5940     break;
5941   case MAT_SPD_ETERNAL:
5942     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");
5943     mat->spd_eternal = flg;
5944     if (flg) {
5945       mat->structural_symmetry_eternal = PETSC_TRUE;
5946       mat->symmetry_eternal            = PETSC_TRUE;
5947     }
5948     break;
5949   case MAT_STRUCTURE_ONLY:
5950     mat->structure_only = flg;
5951     break;
5952   case MAT_SORTED_FULL:
5953     mat->sortedfull = flg;
5954     break;
5955   default:
5956     break;
5957   }
5958   PetscTryTypeMethod(mat, setoption, op, flg);
5959   PetscFunctionReturn(PETSC_SUCCESS);
5960 }
5961 
5962 /*@
5963    MatGetOption - Gets a parameter option that has been set for a matrix.
5964 
5965    Logically Collective
5966 
5967    Input Parameters:
5968 +  mat - the matrix
5969 -  option - the option, this only responds to certain options, check the code for which ones
5970 
5971    Output Parameter:
5972 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5973 
5974    Level: intermediate
5975 
5976     Notes:
5977     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5978 
5979     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5980     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5981 
5982 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5983     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5984 @*/
5985 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5986 {
5987   PetscFunctionBegin;
5988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5989   PetscValidType(mat, 1);
5990 
5991   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);
5992   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()");
5993 
5994   switch (op) {
5995   case MAT_NO_OFF_PROC_ENTRIES:
5996     *flg = mat->nooffprocentries;
5997     break;
5998   case MAT_NO_OFF_PROC_ZERO_ROWS:
5999     *flg = mat->nooffproczerorows;
6000     break;
6001   case MAT_SYMMETRIC:
6002     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6003     break;
6004   case MAT_HERMITIAN:
6005     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6006     break;
6007   case MAT_STRUCTURALLY_SYMMETRIC:
6008     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6009     break;
6010   case MAT_SPD:
6011     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6012     break;
6013   case MAT_SYMMETRY_ETERNAL:
6014     *flg = mat->symmetry_eternal;
6015     break;
6016   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6017     *flg = mat->symmetry_eternal;
6018     break;
6019   default:
6020     break;
6021   }
6022   PetscFunctionReturn(PETSC_SUCCESS);
6023 }
6024 
6025 /*@
6026    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6027    this routine retains the old nonzero structure.
6028 
6029    Logically Collective
6030 
6031    Input Parameters:
6032 .  mat - the matrix
6033 
6034    Level: intermediate
6035 
6036    Note:
6037     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.
6038    See the Performance chapter of the users manual for information on preallocating matrices.
6039 
6040 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6041 @*/
6042 PetscErrorCode MatZeroEntries(Mat mat)
6043 {
6044   PetscFunctionBegin;
6045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6046   PetscValidType(mat, 1);
6047   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6048   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");
6049   MatCheckPreallocated(mat, 1);
6050 
6051   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6052   PetscUseTypeMethod(mat, zeroentries);
6053   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6054   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6055   PetscFunctionReturn(PETSC_SUCCESS);
6056 }
6057 
6058 /*@
6059    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6060    of a set of rows and columns of a matrix.
6061 
6062    Collective
6063 
6064    Input Parameters:
6065 +  mat - the matrix
6066 .  numRows - the number of rows/columns to zero
6067 .  rows - the global row indices
6068 .  diag - value put in the diagonal of the eliminated rows
6069 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6070 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6071 
6072    Level: intermediate
6073 
6074    Notes:
6075    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6076 
6077    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6078    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
6079 
6080    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6081    Krylov method to take advantage of the known solution on the zeroed rows.
6082 
6083    For the parallel case, all processes that share the matrix (i.e.,
6084    those in the communicator used for matrix creation) MUST call this
6085    routine, regardless of whether any rows being zeroed are owned by
6086    them.
6087 
6088    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6089 
6090    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6091    list only rows local to itself).
6092 
6093    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6094 
6095 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6096           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6097 @*/
6098 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6099 {
6100   PetscFunctionBegin;
6101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6102   PetscValidType(mat, 1);
6103   if (numRows) PetscValidIntPointer(rows, 3);
6104   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6105   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6106   MatCheckPreallocated(mat, 1);
6107 
6108   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6109   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6110   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6111   PetscFunctionReturn(PETSC_SUCCESS);
6112 }
6113 
6114 /*@
6115    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6116    of a set of rows and columns of a matrix.
6117 
6118    Collective
6119 
6120    Input Parameters:
6121 +  mat - the matrix
6122 .  is - the rows to zero
6123 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6124 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6125 -  b - optional vector of right hand side, that will be adjusted by provided solution
6126 
6127    Level: intermediate
6128 
6129    Note:
6130    See `MatZeroRowsColumns()` for details on how this routine operates.
6131 
6132 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6133           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6134 @*/
6135 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6136 {
6137   PetscInt        numRows;
6138   const PetscInt *rows;
6139 
6140   PetscFunctionBegin;
6141   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6142   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6143   PetscValidType(mat, 1);
6144   PetscValidType(is, 2);
6145   PetscCall(ISGetLocalSize(is, &numRows));
6146   PetscCall(ISGetIndices(is, &rows));
6147   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6148   PetscCall(ISRestoreIndices(is, &rows));
6149   PetscFunctionReturn(PETSC_SUCCESS);
6150 }
6151 
6152 /*@
6153    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6154    of a set of rows of a matrix.
6155 
6156    Collective
6157 
6158    Input Parameters:
6159 +  mat - the matrix
6160 .  numRows - the number of rows to zero
6161 .  rows - the global row indices
6162 .  diag - value put in the diagonal of the zeroed rows
6163 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6164 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6165 
6166    Level: intermediate
6167 
6168    Notes:
6169    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6170 
6171    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6172 
6173    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6174    Krylov method to take advantage of the known solution on the zeroed rows.
6175 
6176    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)
6177    from the matrix.
6178 
6179    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6180    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
6181    formats this does not alter the nonzero structure.
6182 
6183    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6184    of the matrix is not changed the values are
6185    merely zeroed.
6186 
6187    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6188    formats can optionally remove the main diagonal entry from the
6189    nonzero structure as well, by passing 0.0 as the final argument).
6190 
6191    For the parallel case, all processes that share the matrix (i.e.,
6192    those in the communicator used for matrix creation) MUST call this
6193    routine, regardless of whether any rows being zeroed are owned by
6194    them.
6195 
6196    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6197    list only rows local to itself).
6198 
6199    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6200    owns that are to be zeroed. This saves a global synchronization in the implementation.
6201 
6202 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6203           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6204 @*/
6205 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6206 {
6207   PetscFunctionBegin;
6208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6209   PetscValidType(mat, 1);
6210   if (numRows) PetscValidIntPointer(rows, 3);
6211   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6212   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6213   MatCheckPreallocated(mat, 1);
6214 
6215   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6216   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6217   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6218   PetscFunctionReturn(PETSC_SUCCESS);
6219 }
6220 
6221 /*@
6222    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6223    of a set of rows of a matrix.
6224 
6225    Collective
6226 
6227    Input Parameters:
6228 +  mat - the matrix
6229 .  is - index set of rows to remove (if `NULL` then no row is removed)
6230 .  diag - value put in all diagonals of eliminated rows
6231 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6232 -  b - optional vector of right hand side, that will be adjusted by provided solution
6233 
6234    Level: intermediate
6235 
6236    Note:
6237    See `MatZeroRows()` for details on how this routine operates.
6238 
6239 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6240           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6241 @*/
6242 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6243 {
6244   PetscInt        numRows = 0;
6245   const PetscInt *rows    = NULL;
6246 
6247   PetscFunctionBegin;
6248   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6249   PetscValidType(mat, 1);
6250   if (is) {
6251     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6252     PetscCall(ISGetLocalSize(is, &numRows));
6253     PetscCall(ISGetIndices(is, &rows));
6254   }
6255   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6256   if (is) PetscCall(ISRestoreIndices(is, &rows));
6257   PetscFunctionReturn(PETSC_SUCCESS);
6258 }
6259 
6260 /*@
6261    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6262    of a set of rows of a matrix. These rows must be local to the process.
6263 
6264    Collective
6265 
6266    Input Parameters:
6267 +  mat - the matrix
6268 .  numRows - the number of rows to remove
6269 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6270 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6271 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6272 -  b - optional vector of right hand side, that will be adjusted by provided solution
6273 
6274    Level: intermediate
6275 
6276    Notes:
6277    See `MatZeroRows()` for details on how this routine operates.
6278 
6279    The grid coordinates are across the entire grid, not just the local portion
6280 
6281    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6282    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6283    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6284    `DM_BOUNDARY_PERIODIC` boundary type.
6285 
6286    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
6287    a single value per point) you can skip filling those indices.
6288 
6289    Fortran Note:
6290    `idxm` and `idxn` should be declared as
6291 $     MatStencil idxm(4,m)
6292    and the values inserted using
6293 .vb
6294     idxm(MatStencil_i,1) = i
6295     idxm(MatStencil_j,1) = j
6296     idxm(MatStencil_k,1) = k
6297     idxm(MatStencil_c,1) = c
6298    etc
6299 .ve
6300 
6301 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6302           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6303 @*/
6304 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6305 {
6306   PetscInt  dim    = mat->stencil.dim;
6307   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6308   PetscInt *dims   = mat->stencil.dims + 1;
6309   PetscInt *starts = mat->stencil.starts;
6310   PetscInt *dxm    = (PetscInt *)rows;
6311   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6312 
6313   PetscFunctionBegin;
6314   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6315   PetscValidType(mat, 1);
6316   if (numRows) PetscValidPointer(rows, 3);
6317 
6318   PetscCall(PetscMalloc1(numRows, &jdxm));
6319   for (i = 0; i < numRows; ++i) {
6320     /* Skip unused dimensions (they are ordered k, j, i, c) */
6321     for (j = 0; j < 3 - sdim; ++j) dxm++;
6322     /* Local index in X dir */
6323     tmp = *dxm++ - starts[0];
6324     /* Loop over remaining dimensions */
6325     for (j = 0; j < dim - 1; ++j) {
6326       /* If nonlocal, set index to be negative */
6327       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6328       /* Update local index */
6329       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6330     }
6331     /* Skip component slot if necessary */
6332     if (mat->stencil.noc) dxm++;
6333     /* Local row number */
6334     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6335   }
6336   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6337   PetscCall(PetscFree(jdxm));
6338   PetscFunctionReturn(PETSC_SUCCESS);
6339 }
6340 
6341 /*@
6342    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6343    of a set of rows and columns of a matrix.
6344 
6345    Collective
6346 
6347    Input Parameters:
6348 +  mat - the matrix
6349 .  numRows - the number of rows/columns to remove
6350 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6351 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6352 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6353 -  b - optional vector of right hand side, that will be adjusted by provided solution
6354 
6355    Level: intermediate
6356 
6357    Notes:
6358    See `MatZeroRowsColumns()` for details on how this routine operates.
6359 
6360    The grid coordinates are across the entire grid, not just the local portion
6361 
6362    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6363    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6364    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6365    `DM_BOUNDARY_PERIODIC` boundary type.
6366 
6367    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
6368    a single value per point) you can skip filling those indices.
6369 
6370    Fortran Note:
6371    `idxm` and `idxn` should be declared as
6372 $     MatStencil idxm(4,m)
6373    and the values inserted using
6374 .vb
6375     idxm(MatStencil_i,1) = i
6376     idxm(MatStencil_j,1) = j
6377     idxm(MatStencil_k,1) = k
6378     idxm(MatStencil_c,1) = c
6379     etc
6380 .ve
6381 
6382 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6383           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6384 @*/
6385 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6386 {
6387   PetscInt  dim    = mat->stencil.dim;
6388   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6389   PetscInt *dims   = mat->stencil.dims + 1;
6390   PetscInt *starts = mat->stencil.starts;
6391   PetscInt *dxm    = (PetscInt *)rows;
6392   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6393 
6394   PetscFunctionBegin;
6395   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6396   PetscValidType(mat, 1);
6397   if (numRows) PetscValidPointer(rows, 3);
6398 
6399   PetscCall(PetscMalloc1(numRows, &jdxm));
6400   for (i = 0; i < numRows; ++i) {
6401     /* Skip unused dimensions (they are ordered k, j, i, c) */
6402     for (j = 0; j < 3 - sdim; ++j) dxm++;
6403     /* Local index in X dir */
6404     tmp = *dxm++ - starts[0];
6405     /* Loop over remaining dimensions */
6406     for (j = 0; j < dim - 1; ++j) {
6407       /* If nonlocal, set index to be negative */
6408       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6409       /* Update local index */
6410       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6411     }
6412     /* Skip component slot if necessary */
6413     if (mat->stencil.noc) dxm++;
6414     /* Local row number */
6415     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6416   }
6417   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6418   PetscCall(PetscFree(jdxm));
6419   PetscFunctionReturn(PETSC_SUCCESS);
6420 }
6421 
6422 /*@C
6423    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6424    of a set of rows of a matrix; using local numbering of rows.
6425 
6426    Collective
6427 
6428    Input Parameters:
6429 +  mat - the matrix
6430 .  numRows - the number of rows to remove
6431 .  rows - the local row indices
6432 .  diag - value put in all diagonals of eliminated rows
6433 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6434 -  b - optional vector of right hand side, that will be adjusted by provided solution
6435 
6436    Level: intermediate
6437 
6438    Notes:
6439    Before calling `MatZeroRowsLocal()`, the user must first set the
6440    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6441 
6442    See `MatZeroRows()` for details on how this routine operates.
6443 
6444 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6445           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6446 @*/
6447 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6448 {
6449   PetscFunctionBegin;
6450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6451   PetscValidType(mat, 1);
6452   if (numRows) PetscValidIntPointer(rows, 3);
6453   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6454   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6455   MatCheckPreallocated(mat, 1);
6456 
6457   if (mat->ops->zerorowslocal) {
6458     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6459   } else {
6460     IS              is, newis;
6461     const PetscInt *newRows;
6462 
6463     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6464     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6465     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6466     PetscCall(ISGetIndices(newis, &newRows));
6467     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6468     PetscCall(ISRestoreIndices(newis, &newRows));
6469     PetscCall(ISDestroy(&newis));
6470     PetscCall(ISDestroy(&is));
6471   }
6472   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6473   PetscFunctionReturn(PETSC_SUCCESS);
6474 }
6475 
6476 /*@
6477    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6478    of a set of rows of a matrix; using local numbering of rows.
6479 
6480    Collective
6481 
6482    Input Parameters:
6483 +  mat - the matrix
6484 .  is - index set of rows to remove
6485 .  diag - value put in all diagonals of eliminated rows
6486 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6487 -  b - optional vector of right hand side, that will be adjusted by provided solution
6488 
6489    Level: intermediate
6490 
6491    Notes:
6492    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6493    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6494 
6495    See `MatZeroRows()` for details on how this routine operates.
6496 
6497 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6498           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6499 @*/
6500 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6501 {
6502   PetscInt        numRows;
6503   const PetscInt *rows;
6504 
6505   PetscFunctionBegin;
6506   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6507   PetscValidType(mat, 1);
6508   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6509   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6510   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6511   MatCheckPreallocated(mat, 1);
6512 
6513   PetscCall(ISGetLocalSize(is, &numRows));
6514   PetscCall(ISGetIndices(is, &rows));
6515   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6516   PetscCall(ISRestoreIndices(is, &rows));
6517   PetscFunctionReturn(PETSC_SUCCESS);
6518 }
6519 
6520 /*@
6521    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6522    of a set of rows and columns of a matrix; using local numbering of rows.
6523 
6524    Collective
6525 
6526    Input Parameters:
6527 +  mat - the matrix
6528 .  numRows - the number of rows to remove
6529 .  rows - the global row indices
6530 .  diag - value put in all diagonals of eliminated rows
6531 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6532 -  b - optional vector of right hand side, that will be adjusted by provided solution
6533 
6534    Level: intermediate
6535 
6536    Notes:
6537    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6538    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6539 
6540    See `MatZeroRowsColumns()` for details on how this routine operates.
6541 
6542 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6543           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6544 @*/
6545 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6546 {
6547   IS              is, newis;
6548   const PetscInt *newRows;
6549 
6550   PetscFunctionBegin;
6551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6552   PetscValidType(mat, 1);
6553   if (numRows) PetscValidIntPointer(rows, 3);
6554   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6555   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6556   MatCheckPreallocated(mat, 1);
6557 
6558   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6559   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6560   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6561   PetscCall(ISGetIndices(newis, &newRows));
6562   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6563   PetscCall(ISRestoreIndices(newis, &newRows));
6564   PetscCall(ISDestroy(&newis));
6565   PetscCall(ISDestroy(&is));
6566   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6567   PetscFunctionReturn(PETSC_SUCCESS);
6568 }
6569 
6570 /*@
6571    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6572    of a set of rows and columns of a matrix; using local numbering of rows.
6573 
6574    Collective
6575 
6576    Input Parameters:
6577 +  mat - the matrix
6578 .  is - index set of rows to remove
6579 .  diag - value put in all diagonals of eliminated rows
6580 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6581 -  b - optional vector of right hand side, that will be adjusted by provided solution
6582 
6583    Level: intermediate
6584 
6585    Notes:
6586    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6587    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6588 
6589    See `MatZeroRowsColumns()` for details on how this routine operates.
6590 
6591 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6592           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6593 @*/
6594 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6595 {
6596   PetscInt        numRows;
6597   const PetscInt *rows;
6598 
6599   PetscFunctionBegin;
6600   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6601   PetscValidType(mat, 1);
6602   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6603   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6604   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6605   MatCheckPreallocated(mat, 1);
6606 
6607   PetscCall(ISGetLocalSize(is, &numRows));
6608   PetscCall(ISGetIndices(is, &rows));
6609   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6610   PetscCall(ISRestoreIndices(is, &rows));
6611   PetscFunctionReturn(PETSC_SUCCESS);
6612 }
6613 
6614 /*@C
6615    MatGetSize - Returns the numbers of rows and columns in a matrix.
6616 
6617    Not Collective
6618 
6619    Input Parameter:
6620 .  mat - the matrix
6621 
6622    Level: beginner
6623 
6624    Output Parameters:
6625 +  m - the number of global rows
6626 -  n - the number of global columns
6627 
6628    Note:
6629    Both output parameters can be `NULL` on input.
6630 
6631 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6632 @*/
6633 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6634 {
6635   PetscFunctionBegin;
6636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6637   if (m) *m = mat->rmap->N;
6638   if (n) *n = mat->cmap->N;
6639   PetscFunctionReturn(PETSC_SUCCESS);
6640 }
6641 
6642 /*@C
6643    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6644    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6645 
6646    Not Collective
6647 
6648    Input Parameter:
6649 .  mat - the matrix
6650 
6651    Output Parameters:
6652 +  m - the number of local rows, use `NULL` to not obtain this value
6653 -  n - the number of local columns, use `NULL` to not obtain this value
6654 
6655    Level: beginner
6656 
6657 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6658 @*/
6659 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6660 {
6661   PetscFunctionBegin;
6662   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6663   if (m) PetscValidIntPointer(m, 2);
6664   if (n) PetscValidIntPointer(n, 3);
6665   if (m) *m = mat->rmap->n;
6666   if (n) *n = mat->cmap->n;
6667   PetscFunctionReturn(PETSC_SUCCESS);
6668 }
6669 
6670 /*@C
6671    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6672    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6673 
6674    Not Collective, unless matrix has not been allocated, then collective
6675 
6676    Input Parameter:
6677 .  mat - the matrix
6678 
6679    Output Parameters:
6680 +  m - the global index of the first local column, use `NULL` to not obtain this value
6681 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6682 
6683    Level: developer
6684 
6685 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6686 @*/
6687 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6688 {
6689   PetscFunctionBegin;
6690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6691   PetscValidType(mat, 1);
6692   if (m) PetscValidIntPointer(m, 2);
6693   if (n) PetscValidIntPointer(n, 3);
6694   MatCheckPreallocated(mat, 1);
6695   if (m) *m = mat->cmap->rstart;
6696   if (n) *n = mat->cmap->rend;
6697   PetscFunctionReturn(PETSC_SUCCESS);
6698 }
6699 
6700 /*@C
6701    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6702    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
6703    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6704 
6705    Not Collective
6706 
6707    Input Parameter:
6708 .  mat - the matrix
6709 
6710    Output Parameters:
6711 +  m - the global index of the first local row, use `NULL` to not obtain this value
6712 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6713 
6714    Level: beginner
6715 
6716    Note:
6717   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6718   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6719   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6720 
6721 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6722           `PetscLayout`
6723 @*/
6724 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6725 {
6726   PetscFunctionBegin;
6727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6728   PetscValidType(mat, 1);
6729   if (m) PetscValidIntPointer(m, 2);
6730   if (n) PetscValidIntPointer(n, 3);
6731   MatCheckPreallocated(mat, 1);
6732   if (m) *m = mat->rmap->rstart;
6733   if (n) *n = mat->rmap->rend;
6734   PetscFunctionReturn(PETSC_SUCCESS);
6735 }
6736 
6737 /*@C
6738    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6739    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
6740    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6741 
6742    Not Collective, unless matrix has not been allocated
6743 
6744    Input Parameters:
6745 .  mat - the matrix
6746 
6747    Output Parameters:
6748 .  ranges - start of each processors portion plus one more than the total length at the end
6749 
6750    Level: beginner
6751 
6752 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6753 @*/
6754 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6755 {
6756   PetscFunctionBegin;
6757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6758   PetscValidType(mat, 1);
6759   MatCheckPreallocated(mat, 1);
6760   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6761   PetscFunctionReturn(PETSC_SUCCESS);
6762 }
6763 
6764 /*@C
6765    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6766    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6767 
6768    Not Collective, unless matrix has not been allocated
6769 
6770    Input Parameters:
6771 .  mat - the matrix
6772 
6773    Output Parameters:
6774 .  ranges - start of each processors portion plus one more then the total length at the end
6775 
6776    Level: beginner
6777 
6778 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6779 @*/
6780 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6781 {
6782   PetscFunctionBegin;
6783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6784   PetscValidType(mat, 1);
6785   MatCheckPreallocated(mat, 1);
6786   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6787   PetscFunctionReturn(PETSC_SUCCESS);
6788 }
6789 
6790 /*@C
6791    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6792    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6793    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6794 
6795    Not Collective
6796 
6797    Input Parameter:
6798 .  A - matrix
6799 
6800    Output Parameters:
6801 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6802 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6803 
6804    Level: intermediate
6805 
6806 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6807 @*/
6808 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6809 {
6810   PetscErrorCode (*f)(Mat, IS *, IS *);
6811 
6812   PetscFunctionBegin;
6813   MatCheckPreallocated(A, 1);
6814   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6815   if (f) {
6816     PetscCall((*f)(A, rows, cols));
6817   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6818     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6819     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6820   }
6821   PetscFunctionReturn(PETSC_SUCCESS);
6822 }
6823 
6824 /*@C
6825    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6826    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6827    to complete the factorization.
6828 
6829    Collective
6830 
6831    Input Parameters:
6832 +  fact - the factorized matrix obtained with `MatGetFactor()`
6833 .  mat - the matrix
6834 .  row - row permutation
6835 .  column - column permutation
6836 -  info - structure containing
6837 .vb
6838       levels - number of levels of fill.
6839       expected fill - as ratio of original fill.
6840       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6841                 missing diagonal entries)
6842 .ve
6843 
6844    Output Parameters:
6845 .  fact - new matrix that has been symbolically factored
6846 
6847    Level: developer
6848 
6849    Notes:
6850    See [Matrix Factorization](sec_matfactor) for additional information.
6851 
6852    Most users should employ the `KSP` interface for linear solvers
6853    instead of working directly with matrix algebra routines such as this.
6854    See, e.g., `KSPCreate()`.
6855 
6856    Uses the definition of level of fill as in Y. Saad, 2003
6857 
6858    Developer Note:
6859    The Fortran interface is not autogenerated as the
6860    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6861 
6862    References:
6863 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6864 
6865 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6866           `MatGetOrdering()`, `MatFactorInfo`
6867 @*/
6868 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6869 {
6870   PetscFunctionBegin;
6871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6872   PetscValidType(mat, 2);
6873   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6874   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6875   PetscValidPointer(info, 5);
6876   PetscValidPointer(fact, 1);
6877   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6878   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6879   if (!fact->ops->ilufactorsymbolic) {
6880     MatSolverType stype;
6881     PetscCall(MatFactorGetSolverType(fact, &stype));
6882     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6883   }
6884   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6885   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6886   MatCheckPreallocated(mat, 2);
6887 
6888   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6889   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6890   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6891   PetscFunctionReturn(PETSC_SUCCESS);
6892 }
6893 
6894 /*@C
6895    MatICCFactorSymbolic - Performs symbolic incomplete
6896    Cholesky factorization for a symmetric matrix.  Use
6897    `MatCholeskyFactorNumeric()` to complete the factorization.
6898 
6899    Collective
6900 
6901    Input Parameters:
6902 +  fact - the factorized matrix obtained with `MatGetFactor()`
6903 .  mat - the matrix to be factored
6904 .  perm - row and column permutation
6905 -  info - structure containing
6906 .vb
6907       levels - number of levels of fill.
6908       expected fill - as ratio of original fill.
6909 .ve
6910 
6911    Output Parameter:
6912 .  fact - the factored matrix
6913 
6914    Level: developer
6915 
6916    Notes:
6917    Most users should employ the `KSP` interface for linear solvers
6918    instead of working directly with matrix algebra routines such as this.
6919    See, e.g., `KSPCreate()`.
6920 
6921    This uses the definition of level of fill as in Y. Saad, 2003
6922 
6923    Developer Note:
6924    The Fortran interface is not autogenerated as the
6925    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6926 
6927    References:
6928 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6929 
6930 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6931 @*/
6932 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6933 {
6934   PetscFunctionBegin;
6935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6936   PetscValidType(mat, 2);
6937   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6938   PetscValidPointer(info, 4);
6939   PetscValidPointer(fact, 1);
6940   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6941   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6942   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6943   if (!(fact)->ops->iccfactorsymbolic) {
6944     MatSolverType stype;
6945     PetscCall(MatFactorGetSolverType(fact, &stype));
6946     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6947   }
6948   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6949   MatCheckPreallocated(mat, 2);
6950 
6951   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6952   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6953   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6954   PetscFunctionReturn(PETSC_SUCCESS);
6955 }
6956 
6957 /*@C
6958    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6959    points to an array of valid matrices, they may be reused to store the new
6960    submatrices.
6961 
6962    Collective
6963 
6964    Input Parameters:
6965 +  mat - the matrix
6966 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6967 .  irow, icol - index sets of rows and columns to extract
6968 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6969 
6970    Output Parameter:
6971 .  submat - the array of submatrices
6972 
6973    Level: advanced
6974 
6975    Notes:
6976    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6977    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6978    to extract a parallel submatrix.
6979 
6980    Some matrix types place restrictions on the row and column
6981    indices, such as that they be sorted or that they be equal to each other.
6982 
6983    The index sets may not have duplicate entries.
6984 
6985    When extracting submatrices from a parallel matrix, each processor can
6986    form a different submatrix by setting the rows and columns of its
6987    individual index sets according to the local submatrix desired.
6988 
6989    When finished using the submatrices, the user should destroy
6990    them with `MatDestroySubMatrices()`.
6991 
6992    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6993    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6994 
6995    This routine creates the matrices in submat; you should NOT create them before
6996    calling it. It also allocates the array of matrix pointers submat.
6997 
6998    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6999    request one row/column in a block, they must request all rows/columns that are in
7000    that block. For example, if the block size is 2 you cannot request just row 0 and
7001    column 0.
7002 
7003    Fortran Note:
7004    The Fortran interface is slightly different from that given below; it
7005    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7006 
7007 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7008 @*/
7009 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7010 {
7011   PetscInt  i;
7012   PetscBool eq;
7013 
7014   PetscFunctionBegin;
7015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7016   PetscValidType(mat, 1);
7017   if (n) {
7018     PetscValidPointer(irow, 3);
7019     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7020     PetscValidPointer(icol, 4);
7021     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7022   }
7023   PetscValidPointer(submat, 6);
7024   if (n && scall == MAT_REUSE_MATRIX) {
7025     PetscValidPointer(*submat, 6);
7026     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7027   }
7028   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7029   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7030   MatCheckPreallocated(mat, 1);
7031   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7032   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7033   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7034   for (i = 0; i < n; i++) {
7035     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7036     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7037     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7038 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7039     if (mat->boundtocpu && mat->bindingpropagates) {
7040       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7041       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7042     }
7043 #endif
7044   }
7045   PetscFunctionReturn(PETSC_SUCCESS);
7046 }
7047 
7048 /*@C
7049    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7050 
7051    Collective
7052 
7053    Input Parameters:
7054 +  mat - the matrix
7055 .  n   - the number of submatrixes to be extracted
7056 .  irow, icol - index sets of rows and columns to extract
7057 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7058 
7059    Output Parameter:
7060 .  submat - the array of submatrices
7061 
7062    Level: advanced
7063 
7064    Note:
7065    This is used by `PCGASM`
7066 
7067 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7068 @*/
7069 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7070 {
7071   PetscInt  i;
7072   PetscBool eq;
7073 
7074   PetscFunctionBegin;
7075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7076   PetscValidType(mat, 1);
7077   if (n) {
7078     PetscValidPointer(irow, 3);
7079     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7080     PetscValidPointer(icol, 4);
7081     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7082   }
7083   PetscValidPointer(submat, 6);
7084   if (n && scall == MAT_REUSE_MATRIX) {
7085     PetscValidPointer(*submat, 6);
7086     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7087   }
7088   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7089   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7090   MatCheckPreallocated(mat, 1);
7091 
7092   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7093   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7094   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7095   for (i = 0; i < n; i++) {
7096     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7097     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7098   }
7099   PetscFunctionReturn(PETSC_SUCCESS);
7100 }
7101 
7102 /*@C
7103    MatDestroyMatrices - Destroys an array of matrices.
7104 
7105    Collective
7106 
7107    Input Parameters:
7108 +  n - the number of local matrices
7109 -  mat - the matrices (this is a pointer to the array of matrices)
7110 
7111    Level: advanced
7112 
7113     Note:
7114     Frees not only the matrices, but also the array that contains the matrices
7115 
7116     Fortran Note:
7117     This does not free the array.
7118 
7119 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7120 @*/
7121 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7122 {
7123   PetscInt i;
7124 
7125   PetscFunctionBegin;
7126   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7127   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7128   PetscValidPointer(mat, 2);
7129 
7130   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7131 
7132   /* memory is allocated even if n = 0 */
7133   PetscCall(PetscFree(*mat));
7134   PetscFunctionReturn(PETSC_SUCCESS);
7135 }
7136 
7137 /*@C
7138    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7139 
7140    Collective
7141 
7142    Input Parameters:
7143 +  n - the number of local matrices
7144 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7145                        sequence of `MatCreateSubMatrices()`)
7146 
7147    Level: advanced
7148 
7149     Note:
7150     Frees not only the matrices, but also the array that contains the matrices
7151 
7152     Fortran Note:
7153     This does not free the array.
7154 
7155 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7156 @*/
7157 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7158 {
7159   Mat mat0;
7160 
7161   PetscFunctionBegin;
7162   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7163   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7164   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7165   PetscValidPointer(mat, 2);
7166 
7167   mat0 = (*mat)[0];
7168   if (mat0 && mat0->ops->destroysubmatrices) {
7169     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7170   } else {
7171     PetscCall(MatDestroyMatrices(n, mat));
7172   }
7173   PetscFunctionReturn(PETSC_SUCCESS);
7174 }
7175 
7176 /*@C
7177    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7178 
7179    Collective
7180 
7181    Input Parameters:
7182 .  mat - the matrix
7183 
7184    Output Parameter:
7185 .  matstruct - the sequential matrix with the nonzero structure of mat
7186 
7187   Level: developer
7188 
7189 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7190 @*/
7191 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7192 {
7193   PetscFunctionBegin;
7194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7195   PetscValidPointer(matstruct, 2);
7196 
7197   PetscValidType(mat, 1);
7198   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7199   MatCheckPreallocated(mat, 1);
7200 
7201   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7202   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7203   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7204   PetscFunctionReturn(PETSC_SUCCESS);
7205 }
7206 
7207 /*@C
7208    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7209 
7210    Collective
7211 
7212    Input Parameters:
7213 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7214                        sequence of `MatGetSequentialNonzeroStructure()`)
7215 
7216    Level: advanced
7217 
7218     Note:
7219     Frees not only the matrices, but also the array that contains the matrices
7220 
7221 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7222 @*/
7223 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7224 {
7225   PetscFunctionBegin;
7226   PetscValidPointer(mat, 1);
7227   PetscCall(MatDestroy(mat));
7228   PetscFunctionReturn(PETSC_SUCCESS);
7229 }
7230 
7231 /*@
7232    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7233    replaces the index sets by larger ones that represent submatrices with
7234    additional overlap.
7235 
7236    Collective
7237 
7238    Input Parameters:
7239 +  mat - the matrix
7240 .  n   - the number of index sets
7241 .  is  - the array of index sets (these index sets will changed during the call)
7242 -  ov  - the additional overlap requested
7243 
7244    Options Database Key:
7245 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7246 
7247    Level: developer
7248 
7249    Note:
7250    The computed overlap preserves the matrix block sizes when the blocks are square.
7251    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7252    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7253 
7254 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7255 @*/
7256 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7257 {
7258   PetscInt i, bs, cbs;
7259 
7260   PetscFunctionBegin;
7261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7262   PetscValidType(mat, 1);
7263   PetscValidLogicalCollectiveInt(mat, n, 2);
7264   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7265   if (n) {
7266     PetscValidPointer(is, 3);
7267     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7268   }
7269   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7270   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7271   MatCheckPreallocated(mat, 1);
7272 
7273   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7274   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7275   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7276   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7277   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7278   if (bs == cbs) {
7279     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7280   }
7281   PetscFunctionReturn(PETSC_SUCCESS);
7282 }
7283 
7284 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7285 
7286 /*@
7287    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7288    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7289    additional overlap.
7290 
7291    Collective
7292 
7293    Input Parameters:
7294 +  mat - the matrix
7295 .  n   - the number of index sets
7296 .  is  - the array of index sets (these index sets will changed during the call)
7297 -  ov  - the additional overlap requested
7298 
7299 `   Options Database Key:
7300 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7301 
7302    Level: developer
7303 
7304 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7305 @*/
7306 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7307 {
7308   PetscInt i;
7309 
7310   PetscFunctionBegin;
7311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7312   PetscValidType(mat, 1);
7313   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7314   if (n) {
7315     PetscValidPointer(is, 3);
7316     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7317   }
7318   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7319   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7320   MatCheckPreallocated(mat, 1);
7321   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7322   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7323   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7324   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7325   PetscFunctionReturn(PETSC_SUCCESS);
7326 }
7327 
7328 /*@
7329    MatGetBlockSize - Returns the matrix block size.
7330 
7331    Not Collective
7332 
7333    Input Parameter:
7334 .  mat - the matrix
7335 
7336    Output Parameter:
7337 .  bs - block size
7338 
7339    Level: intermediate
7340 
7341    Notes:
7342     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7343 
7344    If the block size has not been set yet this routine returns 1.
7345 
7346 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7347 @*/
7348 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7349 {
7350   PetscFunctionBegin;
7351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7352   PetscValidIntPointer(bs, 2);
7353   *bs = PetscAbs(mat->rmap->bs);
7354   PetscFunctionReturn(PETSC_SUCCESS);
7355 }
7356 
7357 /*@
7358    MatGetBlockSizes - Returns the matrix block row and column sizes.
7359 
7360    Not Collective
7361 
7362    Input Parameter:
7363 .  mat - the matrix
7364 
7365    Output Parameters:
7366 +  rbs - row block size
7367 -  cbs - column block size
7368 
7369    Level: intermediate
7370 
7371    Notes:
7372     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7373     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7374 
7375    If a block size has not been set yet this routine returns 1.
7376 
7377 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7378 @*/
7379 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7380 {
7381   PetscFunctionBegin;
7382   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7383   if (rbs) PetscValidIntPointer(rbs, 2);
7384   if (cbs) PetscValidIntPointer(cbs, 3);
7385   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7386   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7387   PetscFunctionReturn(PETSC_SUCCESS);
7388 }
7389 
7390 /*@
7391    MatSetBlockSize - Sets the matrix block size.
7392 
7393    Logically Collective
7394 
7395    Input Parameters:
7396 +  mat - the matrix
7397 -  bs - block size
7398 
7399    Level: intermediate
7400 
7401    Notes:
7402     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7403     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7404 
7405     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7406     is compatible with the matrix local sizes.
7407 
7408 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7409 @*/
7410 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7411 {
7412   PetscFunctionBegin;
7413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7414   PetscValidLogicalCollectiveInt(mat, bs, 2);
7415   PetscCall(MatSetBlockSizes(mat, bs, bs));
7416   PetscFunctionReturn(PETSC_SUCCESS);
7417 }
7418 
7419 typedef struct {
7420   PetscInt         n;
7421   IS              *is;
7422   Mat             *mat;
7423   PetscObjectState nonzerostate;
7424   Mat              C;
7425 } EnvelopeData;
7426 
7427 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7428 {
7429   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7430   PetscCall(PetscFree(edata->is));
7431   PetscCall(PetscFree(edata));
7432   return PETSC_SUCCESS;
7433 }
7434 
7435 /*
7436    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7437          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7438 
7439    Collective
7440 
7441    Input Parameter:
7442 .  mat - the matrix
7443 
7444    Notes:
7445      There can be zeros within the blocks
7446 
7447      The blocks can overlap between processes, including laying on more than two processes
7448 
7449 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7450 */
7451 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7452 {
7453   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7454   PetscInt          *diag, *odiag, sc;
7455   VecScatter         scatter;
7456   PetscScalar       *seqv;
7457   const PetscScalar *parv;
7458   const PetscInt    *ia, *ja;
7459   PetscBool          set, flag, done;
7460   Mat                AA = mat, A;
7461   MPI_Comm           comm;
7462   PetscMPIInt        rank, size, tag;
7463   MPI_Status         status;
7464   PetscContainer     container;
7465   EnvelopeData      *edata;
7466   Vec                seq, par;
7467   IS                 isglobal;
7468 
7469   PetscFunctionBegin;
7470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7471   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7472   if (!set || !flag) {
7473     /* TOO: only needs nonzero structure of transpose */
7474     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7475     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7476   }
7477   PetscCall(MatAIJGetLocalMat(AA, &A));
7478   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7479   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7480 
7481   PetscCall(MatGetLocalSize(mat, &n, NULL));
7482   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7483   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7484   PetscCallMPI(MPI_Comm_size(comm, &size));
7485   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7486 
7487   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7488 
7489   if (rank > 0) {
7490     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7491     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7492   }
7493   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7494   for (i = 0; i < n; i++) {
7495     env = PetscMax(env, ja[ia[i + 1] - 1]);
7496     II  = rstart + i;
7497     if (env == II) {
7498       starts[lblocks]  = tbs;
7499       sizes[lblocks++] = 1 + II - tbs;
7500       tbs              = 1 + II;
7501     }
7502   }
7503   if (rank < size - 1) {
7504     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7505     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7506   }
7507 
7508   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7509   if (!set || !flag) PetscCall(MatDestroy(&AA));
7510   PetscCall(MatDestroy(&A));
7511 
7512   PetscCall(PetscNew(&edata));
7513   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7514   edata->n = lblocks;
7515   /* create IS needed for extracting blocks from the original matrix */
7516   PetscCall(PetscMalloc1(lblocks, &edata->is));
7517   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7518 
7519   /* Create the resulting inverse matrix structure with preallocation information */
7520   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7521   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7522   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7523   PetscCall(MatSetType(edata->C, MATAIJ));
7524 
7525   /* Communicate the start and end of each row, from each block to the correct rank */
7526   /* TODO: Use PetscSF instead of VecScatter */
7527   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7528   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7529   PetscCall(VecGetArrayWrite(seq, &seqv));
7530   for (PetscInt i = 0; i < lblocks; i++) {
7531     for (PetscInt j = 0; j < sizes[i]; j++) {
7532       seqv[cnt]     = starts[i];
7533       seqv[cnt + 1] = starts[i] + sizes[i];
7534       cnt += 2;
7535     }
7536   }
7537   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7538   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7539   sc -= cnt;
7540   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7541   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7542   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7543   PetscCall(ISDestroy(&isglobal));
7544   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7545   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7546   PetscCall(VecScatterDestroy(&scatter));
7547   PetscCall(VecDestroy(&seq));
7548   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7549   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7550   PetscCall(VecGetArrayRead(par, &parv));
7551   cnt = 0;
7552   PetscCall(MatGetSize(mat, NULL, &n));
7553   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7554     PetscInt start, end, d = 0, od = 0;
7555 
7556     start = (PetscInt)PetscRealPart(parv[cnt]);
7557     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7558     cnt += 2;
7559 
7560     if (start < cstart) {
7561       od += cstart - start + n - cend;
7562       d += cend - cstart;
7563     } else if (start < cend) {
7564       od += n - cend;
7565       d += cend - start;
7566     } else od += n - start;
7567     if (end <= cstart) {
7568       od -= cstart - end + n - cend;
7569       d -= cend - cstart;
7570     } else if (end < cend) {
7571       od -= n - cend;
7572       d -= cend - end;
7573     } else od -= n - end;
7574 
7575     odiag[i] = od;
7576     diag[i]  = d;
7577   }
7578   PetscCall(VecRestoreArrayRead(par, &parv));
7579   PetscCall(VecDestroy(&par));
7580   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7581   PetscCall(PetscFree2(diag, odiag));
7582   PetscCall(PetscFree2(sizes, starts));
7583 
7584   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7585   PetscCall(PetscContainerSetPointer(container, edata));
7586   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7587   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7588   PetscCall(PetscObjectDereference((PetscObject)container));
7589   PetscFunctionReturn(PETSC_SUCCESS);
7590 }
7591 
7592 /*@
7593   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7594 
7595   Collective
7596 
7597   Input Parameters:
7598 . A - the matrix
7599 
7600   Output Parameters:
7601 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7602 
7603   Level: advanced
7604 
7605   Note:
7606      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7607 
7608 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7609 @*/
7610 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7611 {
7612   PetscContainer   container;
7613   EnvelopeData    *edata;
7614   PetscObjectState nonzerostate;
7615 
7616   PetscFunctionBegin;
7617   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7618   if (!container) {
7619     PetscCall(MatComputeVariableBlockEnvelope(A));
7620     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7621   }
7622   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7623   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7624   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7625   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7626 
7627   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7628   *C = edata->C;
7629 
7630   for (PetscInt i = 0; i < edata->n; i++) {
7631     Mat          D;
7632     PetscScalar *dvalues;
7633 
7634     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7635     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7636     PetscCall(MatSeqDenseInvert(D));
7637     PetscCall(MatDenseGetArray(D, &dvalues));
7638     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7639     PetscCall(MatDestroy(&D));
7640   }
7641   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7642   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7643   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7644   PetscFunctionReturn(PETSC_SUCCESS);
7645 }
7646 
7647 /*@
7648    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7649 
7650    Logically Collective
7651 
7652    Input Parameters:
7653 +  mat - the matrix
7654 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7655 -  bsizes - the block sizes
7656 
7657    Level: intermediate
7658 
7659    Notes:
7660     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7661 
7662     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.
7663 
7664 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7665           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7666 @*/
7667 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7668 {
7669   PetscInt i, ncnt = 0, nlocal;
7670 
7671   PetscFunctionBegin;
7672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7673   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7674   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7675   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7676   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);
7677   PetscCall(PetscFree(mat->bsizes));
7678   mat->nblocks = nblocks;
7679   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7680   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7681   PetscFunctionReturn(PETSC_SUCCESS);
7682 }
7683 
7684 /*@C
7685    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7686 
7687    Logically Collective; No Fortran Support
7688 
7689    Input Parameter:
7690 .  mat - the matrix
7691 
7692    Output Parameters:
7693 +  nblocks - the number of blocks on this process
7694 -  bsizes - the block sizes
7695 
7696    Level: intermediate
7697 
7698 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7699 @*/
7700 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7701 {
7702   PetscFunctionBegin;
7703   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7704   *nblocks = mat->nblocks;
7705   *bsizes  = mat->bsizes;
7706   PetscFunctionReturn(PETSC_SUCCESS);
7707 }
7708 
7709 /*@
7710    MatSetBlockSizes - Sets the matrix block row and column sizes.
7711 
7712    Logically Collective
7713 
7714    Input Parameters:
7715 +  mat - the matrix
7716 .  rbs - row block size
7717 -  cbs - column block size
7718 
7719    Level: intermediate
7720 
7721    Notes:
7722     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7723     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7724     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7725 
7726     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7727     are compatible with the matrix local sizes.
7728 
7729     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7730 
7731 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7732 @*/
7733 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7734 {
7735   PetscFunctionBegin;
7736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7737   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7738   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7739   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7740   if (mat->rmap->refcnt) {
7741     ISLocalToGlobalMapping l2g  = NULL;
7742     PetscLayout            nmap = NULL;
7743 
7744     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7745     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7746     PetscCall(PetscLayoutDestroy(&mat->rmap));
7747     mat->rmap          = nmap;
7748     mat->rmap->mapping = l2g;
7749   }
7750   if (mat->cmap->refcnt) {
7751     ISLocalToGlobalMapping l2g  = NULL;
7752     PetscLayout            nmap = NULL;
7753 
7754     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7755     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7756     PetscCall(PetscLayoutDestroy(&mat->cmap));
7757     mat->cmap          = nmap;
7758     mat->cmap->mapping = l2g;
7759   }
7760   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7761   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7762   PetscFunctionReturn(PETSC_SUCCESS);
7763 }
7764 
7765 /*@
7766    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7767 
7768    Logically Collective
7769 
7770    Input Parameters:
7771 +  mat - the matrix
7772 .  fromRow - matrix from which to copy row block size
7773 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7774 
7775    Level: developer
7776 
7777 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7778 @*/
7779 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7780 {
7781   PetscFunctionBegin;
7782   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7783   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7784   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7785   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7786   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7787   PetscFunctionReturn(PETSC_SUCCESS);
7788 }
7789 
7790 /*@
7791    MatResidual - Default routine to calculate the residual r = b - Ax
7792 
7793    Collective
7794 
7795    Input Parameters:
7796 +  mat - the matrix
7797 .  b   - the right-hand-side
7798 -  x   - the approximate solution
7799 
7800    Output Parameter:
7801 .  r - location to store the residual
7802 
7803    Level: developer
7804 
7805 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7806 @*/
7807 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7808 {
7809   PetscFunctionBegin;
7810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7811   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7812   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7813   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7814   PetscValidType(mat, 1);
7815   MatCheckPreallocated(mat, 1);
7816   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7817   if (!mat->ops->residual) {
7818     PetscCall(MatMult(mat, x, r));
7819     PetscCall(VecAYPX(r, -1.0, b));
7820   } else {
7821     PetscUseTypeMethod(mat, residual, b, x, r);
7822   }
7823   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7824   PetscFunctionReturn(PETSC_SUCCESS);
7825 }
7826 
7827 /*MC
7828     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7829 
7830     Synopsis:
7831     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7832 
7833     Not Collective
7834 
7835     Input Parameters:
7836 +   A - the matrix
7837 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7838 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7839 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7840                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7841                  always used.
7842 
7843     Output Parameters:
7844 +   n - number of local rows in the (possibly compressed) matrix
7845 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7846 .   ja - the column indices
7847 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7848            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7849 
7850     Level: developer
7851 
7852     Note:
7853     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7854 
7855 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7856 M*/
7857 
7858 /*MC
7859     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7860 
7861     Synopsis:
7862     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7863 
7864     Not Collective
7865 
7866     Input Parameters:
7867 +   A - the  matrix
7868 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7869 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7870     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7871                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7872                  always used.
7873 .   n - number of local rows in the (possibly compressed) matrix
7874 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7875 .   ja - the column indices
7876 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7877            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7878 
7879     Level: developer
7880 
7881 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7882 M*/
7883 
7884 /*@C
7885     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7886 
7887    Collective
7888 
7889     Input Parameters:
7890 +   mat - the matrix
7891 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7892 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7893 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7894                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7895                  always used.
7896 
7897     Output Parameters:
7898 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7899 .   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
7900 .   ja - the column indices, use `NULL` if not needed
7901 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7902            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7903 
7904     Level: developer
7905 
7906     Notes:
7907     You CANNOT change any of the ia[] or ja[] values.
7908 
7909     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7910 
7911     Fortran Notes:
7912     Use
7913 .vb
7914     PetscInt, pointer :: ia(:),ja(:)
7915     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7916     ! Access the ith and jth entries via ia(i) and ja(j)
7917 .ve
7918    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7919 
7920 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7921 @*/
7922 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7923 {
7924   PetscFunctionBegin;
7925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7926   PetscValidType(mat, 1);
7927   if (n) PetscValidIntPointer(n, 5);
7928   if (ia) PetscValidPointer(ia, 6);
7929   if (ja) PetscValidPointer(ja, 7);
7930   if (done) PetscValidBoolPointer(done, 8);
7931   MatCheckPreallocated(mat, 1);
7932   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7933   else {
7934     if (done) *done = PETSC_TRUE;
7935     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7936     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7937     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7938   }
7939   PetscFunctionReturn(PETSC_SUCCESS);
7940 }
7941 
7942 /*@C
7943     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7944 
7945     Collective
7946 
7947     Input Parameters:
7948 +   mat - the matrix
7949 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7950 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7951                 symmetrized
7952 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7953                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7954                  always used.
7955 .   n - number of columns in the (possibly compressed) matrix
7956 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7957 -   ja - the row indices
7958 
7959     Output Parameters:
7960 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7961 
7962     Level: developer
7963 
7964 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7965 @*/
7966 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7967 {
7968   PetscFunctionBegin;
7969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7970   PetscValidType(mat, 1);
7971   PetscValidIntPointer(n, 5);
7972   if (ia) PetscValidPointer(ia, 6);
7973   if (ja) PetscValidPointer(ja, 7);
7974   PetscValidBoolPointer(done, 8);
7975   MatCheckPreallocated(mat, 1);
7976   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7977   else {
7978     *done = PETSC_TRUE;
7979     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7980   }
7981   PetscFunctionReturn(PETSC_SUCCESS);
7982 }
7983 
7984 /*@C
7985     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7986 
7987     Collective
7988 
7989     Input Parameters:
7990 +   mat - the matrix
7991 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7992 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7993 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7994                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7995                  always used.
7996 .   n - size of (possibly compressed) matrix
7997 .   ia - the row pointers
7998 -   ja - the column indices
7999 
8000     Output Parameters:
8001 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8002 
8003     Level: developer
8004 
8005     Note:
8006     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8007     us of the array after it has been restored. If you pass `NULL`, it will
8008     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8009 
8010     Fortran Note:
8011    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8012 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8013 @*/
8014 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8015 {
8016   PetscFunctionBegin;
8017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8018   PetscValidType(mat, 1);
8019   if (ia) PetscValidPointer(ia, 6);
8020   if (ja) PetscValidPointer(ja, 7);
8021   if (done) PetscValidBoolPointer(done, 8);
8022   MatCheckPreallocated(mat, 1);
8023 
8024   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8025   else {
8026     if (done) *done = PETSC_TRUE;
8027     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8028     if (n) *n = 0;
8029     if (ia) *ia = NULL;
8030     if (ja) *ja = NULL;
8031   }
8032   PetscFunctionReturn(PETSC_SUCCESS);
8033 }
8034 
8035 /*@C
8036     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8037 
8038     Collective
8039 
8040     Input Parameters:
8041 +   mat - the matrix
8042 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8043 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8044 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8045                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8046                  always used.
8047 
8048     Output Parameters:
8049 +   n - size of (possibly compressed) matrix
8050 .   ia - the column pointers
8051 .   ja - the row indices
8052 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8053 
8054     Level: developer
8055 
8056 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8057 @*/
8058 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8059 {
8060   PetscFunctionBegin;
8061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8062   PetscValidType(mat, 1);
8063   if (ia) PetscValidPointer(ia, 6);
8064   if (ja) PetscValidPointer(ja, 7);
8065   PetscValidBoolPointer(done, 8);
8066   MatCheckPreallocated(mat, 1);
8067 
8068   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8069   else {
8070     *done = PETSC_TRUE;
8071     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8072     if (n) *n = 0;
8073     if (ia) *ia = NULL;
8074     if (ja) *ja = NULL;
8075   }
8076   PetscFunctionReturn(PETSC_SUCCESS);
8077 }
8078 
8079 /*@C
8080     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8081 
8082     Collective
8083 
8084     Input Parameters:
8085 +   mat - the matrix
8086 .   ncolors - max color value
8087 .   n   - number of entries in colorarray
8088 -   colorarray - array indicating color for each column
8089 
8090     Output Parameters:
8091 .   iscoloring - coloring generated using colorarray information
8092 
8093     Level: developer
8094 
8095 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8096 @*/
8097 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8098 {
8099   PetscFunctionBegin;
8100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8101   PetscValidType(mat, 1);
8102   PetscValidIntPointer(colorarray, 4);
8103   PetscValidPointer(iscoloring, 5);
8104   MatCheckPreallocated(mat, 1);
8105 
8106   if (!mat->ops->coloringpatch) {
8107     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8108   } else {
8109     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8110   }
8111   PetscFunctionReturn(PETSC_SUCCESS);
8112 }
8113 
8114 /*@
8115    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8116 
8117    Logically Collective
8118 
8119    Input Parameter:
8120 .  mat - the factored matrix to be reset
8121 
8122    Level: developer
8123 
8124    Notes:
8125    This routine should be used only with factored matrices formed by in-place
8126    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8127    format).  This option can save memory, for example, when solving nonlinear
8128    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8129    ILU(0) preconditioner.
8130 
8131    One can specify in-place ILU(0) factorization by calling
8132 .vb
8133      PCType(pc,PCILU);
8134      PCFactorSeUseInPlace(pc);
8135 .ve
8136    or by using the options -pc_type ilu -pc_factor_in_place
8137 
8138    In-place factorization ILU(0) can also be used as a local
8139    solver for the blocks within the block Jacobi or additive Schwarz
8140    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8141    for details on setting local solver options.
8142 
8143    Most users should employ the `KSP` interface for linear solvers
8144    instead of working directly with matrix algebra routines such as this.
8145    See, e.g., `KSPCreate()`.
8146 
8147 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8148 @*/
8149 PetscErrorCode MatSetUnfactored(Mat mat)
8150 {
8151   PetscFunctionBegin;
8152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8153   PetscValidType(mat, 1);
8154   MatCheckPreallocated(mat, 1);
8155   mat->factortype = MAT_FACTOR_NONE;
8156   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8157   PetscUseTypeMethod(mat, setunfactored);
8158   PetscFunctionReturn(PETSC_SUCCESS);
8159 }
8160 
8161 /*MC
8162     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8163 
8164     Synopsis:
8165     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8166 
8167     Not collective
8168 
8169     Input Parameter:
8170 .   x - matrix
8171 
8172     Output Parameters:
8173 +   xx_v - the Fortran pointer to the array
8174 -   ierr - error code
8175 
8176     Example of Usage:
8177 .vb
8178       PetscScalar, pointer xx_v(:,:)
8179       ....
8180       call MatDenseGetArrayF90(x,xx_v,ierr)
8181       a = xx_v(3)
8182       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8183 .ve
8184 
8185     Level: advanced
8186 
8187 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8188 M*/
8189 
8190 /*MC
8191     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8192     accessed with `MatDenseGetArrayF90()`.
8193 
8194     Synopsis:
8195     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8196 
8197     Not collective
8198 
8199     Input Parameters:
8200 +   x - matrix
8201 -   xx_v - the Fortran90 pointer to the array
8202 
8203     Output Parameter:
8204 .   ierr - error code
8205 
8206     Example of Usage:
8207 .vb
8208        PetscScalar, pointer xx_v(:,:)
8209        ....
8210        call MatDenseGetArrayF90(x,xx_v,ierr)
8211        a = xx_v(3)
8212        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8213 .ve
8214 
8215     Level: advanced
8216 
8217 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8218 M*/
8219 
8220 /*MC
8221     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8222 
8223     Synopsis:
8224     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8225 
8226     Not collective
8227 
8228     Input Parameter:
8229 .   x - matrix
8230 
8231     Output Parameters:
8232 +   xx_v - the Fortran pointer to the array
8233 -   ierr - error code
8234 
8235     Example of Usage:
8236 .vb
8237       PetscScalar, pointer xx_v(:)
8238       ....
8239       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8240       a = xx_v(3)
8241       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8242 .ve
8243 
8244     Level: advanced
8245 
8246 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8247 M*/
8248 
8249 /*MC
8250     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8251     accessed with `MatSeqAIJGetArrayF90()`.
8252 
8253     Synopsis:
8254     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8255 
8256     Not collective
8257 
8258     Input Parameters:
8259 +   x - matrix
8260 -   xx_v - the Fortran90 pointer to the array
8261 
8262     Output Parameter:
8263 .   ierr - error code
8264 
8265     Example of Usage:
8266 .vb
8267        PetscScalar, pointer xx_v(:)
8268        ....
8269        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8270        a = xx_v(3)
8271        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8272 .ve
8273 
8274     Level: advanced
8275 
8276 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8277 M*/
8278 
8279 /*@
8280     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8281                       as the original matrix.
8282 
8283     Collective
8284 
8285     Input Parameters:
8286 +   mat - the original matrix
8287 .   isrow - parallel IS containing the rows this processor should obtain
8288 .   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.
8289 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8290 
8291     Output Parameter:
8292 .   newmat - the new submatrix, of the same type as the old
8293 
8294     Level: advanced
8295 
8296     Notes:
8297     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8298 
8299     Some matrix types place restrictions on the row and column indices, such
8300     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;
8301     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8302 
8303     The index sets may not have duplicate entries.
8304 
8305       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8306    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8307    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8308    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8309    you are finished using it.
8310 
8311     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8312     the input matrix.
8313 
8314     If iscol is `NULL` then all columns are obtained (not supported in Fortran).
8315 
8316    Example usage:
8317    Consider the following 8x8 matrix with 34 non-zero values, that is
8318    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8319    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8320    as follows:
8321 
8322 .vb
8323             1  2  0  |  0  3  0  |  0  4
8324     Proc0   0  5  6  |  7  0  0  |  8  0
8325             9  0 10  | 11  0  0  | 12  0
8326     -------------------------------------
8327            13  0 14  | 15 16 17  |  0  0
8328     Proc1   0 18  0  | 19 20 21  |  0  0
8329             0  0  0  | 22 23  0  | 24  0
8330     -------------------------------------
8331     Proc2  25 26 27  |  0  0 28  | 29  0
8332            30  0  0  | 31 32 33  |  0 34
8333 .ve
8334 
8335     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8336 
8337 .vb
8338             2  0  |  0  3  0  |  0
8339     Proc0   5  6  |  7  0  0  |  8
8340     -------------------------------
8341     Proc1  18  0  | 19 20 21  |  0
8342     -------------------------------
8343     Proc2  26 27  |  0  0 28  | 29
8344             0  0  | 31 32 33  |  0
8345 .ve
8346 
8347 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8348 @*/
8349 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8350 {
8351   PetscMPIInt size;
8352   Mat        *local;
8353   IS          iscoltmp;
8354   PetscBool   flg;
8355 
8356   PetscFunctionBegin;
8357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8358   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8359   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8360   PetscValidPointer(newmat, 5);
8361   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8362   PetscValidType(mat, 1);
8363   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8364   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8365 
8366   MatCheckPreallocated(mat, 1);
8367   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8368 
8369   if (!iscol || isrow == iscol) {
8370     PetscBool   stride;
8371     PetscMPIInt grabentirematrix = 0, grab;
8372     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8373     if (stride) {
8374       PetscInt first, step, n, rstart, rend;
8375       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8376       if (step == 1) {
8377         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8378         if (rstart == first) {
8379           PetscCall(ISGetLocalSize(isrow, &n));
8380           if (n == rend - rstart) grabentirematrix = 1;
8381         }
8382       }
8383     }
8384     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8385     if (grab) {
8386       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8387       if (cll == MAT_INITIAL_MATRIX) {
8388         *newmat = mat;
8389         PetscCall(PetscObjectReference((PetscObject)mat));
8390       }
8391       PetscFunctionReturn(PETSC_SUCCESS);
8392     }
8393   }
8394 
8395   if (!iscol) {
8396     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8397   } else {
8398     iscoltmp = iscol;
8399   }
8400 
8401   /* if original matrix is on just one processor then use submatrix generated */
8402   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8403     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8404     goto setproperties;
8405   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8406     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8407     *newmat = *local;
8408     PetscCall(PetscFree(local));
8409     goto setproperties;
8410   } else if (!mat->ops->createsubmatrix) {
8411     /* Create a new matrix type that implements the operation using the full matrix */
8412     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8413     switch (cll) {
8414     case MAT_INITIAL_MATRIX:
8415       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8416       break;
8417     case MAT_REUSE_MATRIX:
8418       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8419       break;
8420     default:
8421       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8422     }
8423     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8424     goto setproperties;
8425   }
8426 
8427   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8428   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8429   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8430 
8431 setproperties:
8432   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8433   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8434   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8435   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8436   PetscFunctionReturn(PETSC_SUCCESS);
8437 }
8438 
8439 /*@
8440    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8441 
8442    Not Collective
8443 
8444    Input Parameters:
8445 +  A - the matrix we wish to propagate options from
8446 -  B - the matrix we wish to propagate options to
8447 
8448    Level: beginner
8449 
8450    Note:
8451    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8452 
8453 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8454 @*/
8455 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8456 {
8457   PetscFunctionBegin;
8458   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8459   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8460   B->symmetry_eternal            = A->symmetry_eternal;
8461   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8462   B->symmetric                   = A->symmetric;
8463   B->structurally_symmetric      = A->structurally_symmetric;
8464   B->spd                         = A->spd;
8465   B->hermitian                   = A->hermitian;
8466   PetscFunctionReturn(PETSC_SUCCESS);
8467 }
8468 
8469 /*@
8470    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8471    used during the assembly process to store values that belong to
8472    other processors.
8473 
8474    Not Collective
8475 
8476    Input Parameters:
8477 +  mat   - the matrix
8478 .  size  - the initial size of the stash.
8479 -  bsize - the initial size of the block-stash(if used).
8480 
8481    Options Database Keys:
8482 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8483 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8484 
8485    Level: intermediate
8486 
8487    Notes:
8488      The block-stash is used for values set with `MatSetValuesBlocked()` while
8489      the stash is used for values set with `MatSetValues()`
8490 
8491      Run with the option -info and look for output of the form
8492      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8493      to determine the appropriate value, MM, to use for size and
8494      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8495      to determine the value, BMM to use for bsize
8496 
8497 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8498 @*/
8499 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8500 {
8501   PetscFunctionBegin;
8502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8503   PetscValidType(mat, 1);
8504   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8505   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8506   PetscFunctionReturn(PETSC_SUCCESS);
8507 }
8508 
8509 /*@
8510    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8511      the matrix
8512 
8513    Neighbor-wise Collective
8514 
8515    Input Parameters:
8516 +  mat   - the matrix
8517 .  x,y - the vectors
8518 -  w - where the result is stored
8519 
8520    Level: intermediate
8521 
8522    Notes:
8523     `w` may be the same vector as `y`.
8524 
8525     This allows one to use either the restriction or interpolation (its transpose)
8526     matrix to do the interpolation
8527 
8528 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8529 @*/
8530 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8531 {
8532   PetscInt M, N, Ny;
8533 
8534   PetscFunctionBegin;
8535   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8536   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8537   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8538   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8539   PetscCall(MatGetSize(A, &M, &N));
8540   PetscCall(VecGetSize(y, &Ny));
8541   if (M == Ny) {
8542     PetscCall(MatMultAdd(A, x, y, w));
8543   } else {
8544     PetscCall(MatMultTransposeAdd(A, x, y, w));
8545   }
8546   PetscFunctionReturn(PETSC_SUCCESS);
8547 }
8548 
8549 /*@
8550    MatInterpolate - y = A*x or A'*x depending on the shape of
8551      the matrix
8552 
8553    Neighbor-wise Collective
8554 
8555    Input Parameters:
8556 +  mat   - the matrix
8557 -  x,y - the vectors
8558 
8559    Level: intermediate
8560 
8561    Note:
8562     This allows one to use either the restriction or interpolation (its transpose)
8563     matrix to do the interpolation
8564 
8565 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8566 @*/
8567 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8568 {
8569   PetscInt M, N, Ny;
8570 
8571   PetscFunctionBegin;
8572   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8573   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8574   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8575   PetscCall(MatGetSize(A, &M, &N));
8576   PetscCall(VecGetSize(y, &Ny));
8577   if (M == Ny) {
8578     PetscCall(MatMult(A, x, y));
8579   } else {
8580     PetscCall(MatMultTranspose(A, x, y));
8581   }
8582   PetscFunctionReturn(PETSC_SUCCESS);
8583 }
8584 
8585 /*@
8586    MatRestrict - y = A*x or A'*x
8587 
8588    Neighbor-wise Collective
8589 
8590    Input Parameters:
8591 +  mat   - the matrix
8592 -  x,y - the vectors
8593 
8594    Level: intermediate
8595 
8596    Note:
8597     This allows one to use either the restriction or interpolation (its transpose)
8598     matrix to do the restriction
8599 
8600 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8601 @*/
8602 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8603 {
8604   PetscInt M, N, Ny;
8605 
8606   PetscFunctionBegin;
8607   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8608   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8609   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8610   PetscCall(MatGetSize(A, &M, &N));
8611   PetscCall(VecGetSize(y, &Ny));
8612   if (M == Ny) {
8613     PetscCall(MatMult(A, x, y));
8614   } else {
8615     PetscCall(MatMultTranspose(A, x, y));
8616   }
8617   PetscFunctionReturn(PETSC_SUCCESS);
8618 }
8619 
8620 /*@
8621    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8622 
8623    Neighbor-wise Collective
8624 
8625    Input Parameters:
8626 +  mat   - the matrix
8627 -  w, x - the input dense matrices
8628 
8629    Output Parameters:
8630 .  y - the output dense matrix
8631 
8632    Level: intermediate
8633 
8634    Note:
8635     This allows one to use either the restriction or interpolation (its transpose)
8636     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8637     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8638 
8639 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8640 @*/
8641 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8642 {
8643   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8644   PetscBool trans = PETSC_TRUE;
8645   MatReuse  reuse = MAT_INITIAL_MATRIX;
8646 
8647   PetscFunctionBegin;
8648   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8649   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8650   PetscValidType(x, 2);
8651   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8652   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8653   PetscCall(MatGetSize(A, &M, &N));
8654   PetscCall(MatGetSize(x, &Mx, &Nx));
8655   if (N == Mx) trans = PETSC_FALSE;
8656   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);
8657   Mo = trans ? N : M;
8658   if (*y) {
8659     PetscCall(MatGetSize(*y, &My, &Ny));
8660     if (Mo == My && Nx == Ny) {
8661       reuse = MAT_REUSE_MATRIX;
8662     } else {
8663       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);
8664       PetscCall(MatDestroy(y));
8665     }
8666   }
8667 
8668   if (w && *y == w) { /* this is to minimize changes in PCMG */
8669     PetscBool flg;
8670 
8671     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8672     if (w) {
8673       PetscInt My, Ny, Mw, Nw;
8674 
8675       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8676       PetscCall(MatGetSize(*y, &My, &Ny));
8677       PetscCall(MatGetSize(w, &Mw, &Nw));
8678       if (!flg || My != Mw || Ny != Nw) w = NULL;
8679     }
8680     if (!w) {
8681       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8682       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8683       PetscCall(PetscObjectDereference((PetscObject)w));
8684     } else {
8685       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8686     }
8687   }
8688   if (!trans) {
8689     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8690   } else {
8691     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8692   }
8693   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8694   PetscFunctionReturn(PETSC_SUCCESS);
8695 }
8696 
8697 /*@
8698    MatMatInterpolate - Y = A*X or A'*X
8699 
8700    Neighbor-wise Collective
8701 
8702    Input Parameters:
8703 +  mat   - the matrix
8704 -  x - the input dense matrix
8705 
8706    Output Parameters:
8707 .  y - the output dense matrix
8708 
8709    Level: intermediate
8710 
8711    Note:
8712     This allows one to use either the restriction or interpolation (its transpose)
8713     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8714     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8715 
8716 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8717 @*/
8718 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8719 {
8720   PetscFunctionBegin;
8721   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8722   PetscFunctionReturn(PETSC_SUCCESS);
8723 }
8724 
8725 /*@
8726    MatMatRestrict - Y = A*X or A'*X
8727 
8728    Neighbor-wise Collective
8729 
8730    Input Parameters:
8731 +  mat   - the matrix
8732 -  x - the input dense matrix
8733 
8734    Output Parameters:
8735 .  y - the output dense matrix
8736 
8737    Level: intermediate
8738 
8739    Note:
8740     This allows one to use either the restriction or interpolation (its transpose)
8741     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8742     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8743 
8744 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8745 @*/
8746 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8747 {
8748   PetscFunctionBegin;
8749   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8750   PetscFunctionReturn(PETSC_SUCCESS);
8751 }
8752 
8753 /*@
8754    MatGetNullSpace - retrieves the null space of a matrix.
8755 
8756    Logically Collective
8757 
8758    Input Parameters:
8759 +  mat - the matrix
8760 -  nullsp - the null space object
8761 
8762    Level: developer
8763 
8764 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8765 @*/
8766 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8767 {
8768   PetscFunctionBegin;
8769   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8770   PetscValidPointer(nullsp, 2);
8771   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8772   PetscFunctionReturn(PETSC_SUCCESS);
8773 }
8774 
8775 /*@
8776    MatSetNullSpace - attaches a null space to a matrix.
8777 
8778    Logically Collective
8779 
8780    Input Parameters:
8781 +  mat - the matrix
8782 -  nullsp - the null space object
8783 
8784    Level: advanced
8785 
8786    Notes:
8787       This null space is used by the `KSP` linear solvers to solve singular systems.
8788 
8789       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`
8790 
8791       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
8792       to zero but the linear system will still be solved in a least squares sense.
8793 
8794       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8795    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).
8796    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
8797    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
8798    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).
8799    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8800 
8801     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8802     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8803     routine also automatically calls `MatSetTransposeNullSpace()`.
8804 
8805     The user should call `MatNullSpaceDestroy()`.
8806 
8807 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8808           `KSPSetPCSide()`
8809 @*/
8810 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8811 {
8812   PetscFunctionBegin;
8813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8814   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8815   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8816   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8817   mat->nullsp = nullsp;
8818   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8819   PetscFunctionReturn(PETSC_SUCCESS);
8820 }
8821 
8822 /*@
8823    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8824 
8825    Logically Collective
8826 
8827    Input Parameters:
8828 +  mat - the matrix
8829 -  nullsp - the null space object
8830 
8831    Level: developer
8832 
8833 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8834 @*/
8835 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8836 {
8837   PetscFunctionBegin;
8838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8839   PetscValidType(mat, 1);
8840   PetscValidPointer(nullsp, 2);
8841   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8842   PetscFunctionReturn(PETSC_SUCCESS);
8843 }
8844 
8845 /*@
8846    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8847 
8848    Logically Collective
8849 
8850    Input Parameters:
8851 +  mat - the matrix
8852 -  nullsp - the null space object
8853 
8854    Level: advanced
8855 
8856    Notes:
8857    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8858 
8859    See `MatSetNullSpace()`
8860 
8861 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8862 @*/
8863 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8864 {
8865   PetscFunctionBegin;
8866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8867   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8868   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8869   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8870   mat->transnullsp = nullsp;
8871   PetscFunctionReturn(PETSC_SUCCESS);
8872 }
8873 
8874 /*@
8875    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8876         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8877 
8878    Logically Collective
8879 
8880    Input Parameters:
8881 +  mat - the matrix
8882 -  nullsp - the null space object
8883 
8884    Level: advanced
8885 
8886    Notes:
8887    Overwrites any previous near null space that may have been attached
8888 
8889    You can remove the null space by calling this routine with an nullsp of `NULL`
8890 
8891 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8892 @*/
8893 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8894 {
8895   PetscFunctionBegin;
8896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8897   PetscValidType(mat, 1);
8898   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8899   MatCheckPreallocated(mat, 1);
8900   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8901   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8902   mat->nearnullsp = nullsp;
8903   PetscFunctionReturn(PETSC_SUCCESS);
8904 }
8905 
8906 /*@
8907    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8908 
8909    Not Collective
8910 
8911    Input Parameter:
8912 .  mat - the matrix
8913 
8914    Output Parameter:
8915 .  nullsp - the null space object, `NULL` if not set
8916 
8917    Level: advanced
8918 
8919 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8920 @*/
8921 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8922 {
8923   PetscFunctionBegin;
8924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8925   PetscValidType(mat, 1);
8926   PetscValidPointer(nullsp, 2);
8927   MatCheckPreallocated(mat, 1);
8928   *nullsp = mat->nearnullsp;
8929   PetscFunctionReturn(PETSC_SUCCESS);
8930 }
8931 
8932 /*@C
8933    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8934 
8935    Collective
8936 
8937    Input Parameters:
8938 +  mat - the matrix
8939 .  row - row/column permutation
8940 .  fill - expected fill factor >= 1.0
8941 -  level - level of fill, for ICC(k)
8942 
8943    Notes:
8944    Probably really in-place only when level of fill is zero, otherwise allocates
8945    new space to store factored matrix and deletes previous memory.
8946 
8947    Most users should employ the `KSP` interface for linear solvers
8948    instead of working directly with matrix algebra routines such as this.
8949    See, e.g., `KSPCreate()`.
8950 
8951    Level: developer
8952 
8953    Developer Note:
8954    The Fortran interface is not autogenerated as the
8955    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8956 
8957 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8958 @*/
8959 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8960 {
8961   PetscFunctionBegin;
8962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8963   PetscValidType(mat, 1);
8964   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8965   PetscValidPointer(info, 3);
8966   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8967   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8968   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8969   MatCheckPreallocated(mat, 1);
8970   PetscUseTypeMethod(mat, iccfactor, row, info);
8971   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8972   PetscFunctionReturn(PETSC_SUCCESS);
8973 }
8974 
8975 /*@
8976    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8977          ghosted ones.
8978 
8979    Not Collective
8980 
8981    Input Parameters:
8982 +  mat - the matrix
8983 -  diag - the diagonal values, including ghost ones
8984 
8985    Level: developer
8986 
8987    Notes:
8988     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8989 
8990     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8991 
8992 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8993 @*/
8994 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8995 {
8996   PetscMPIInt size;
8997 
8998   PetscFunctionBegin;
8999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9000   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9001   PetscValidType(mat, 1);
9002 
9003   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9004   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9005   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9006   if (size == 1) {
9007     PetscInt n, m;
9008     PetscCall(VecGetSize(diag, &n));
9009     PetscCall(MatGetSize(mat, NULL, &m));
9010     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9011     PetscCall(MatDiagonalScale(mat, NULL, diag));
9012   } else {
9013     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9014   }
9015   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9016   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9017   PetscFunctionReturn(PETSC_SUCCESS);
9018 }
9019 
9020 /*@
9021    MatGetInertia - Gets the inertia from a factored matrix
9022 
9023    Collective
9024 
9025    Input Parameter:
9026 .  mat - the matrix
9027 
9028    Output Parameters:
9029 +   nneg - number of negative eigenvalues
9030 .   nzero - number of zero eigenvalues
9031 -   npos - number of positive eigenvalues
9032 
9033    Level: advanced
9034 
9035    Note:
9036     Matrix must have been factored by `MatCholeskyFactor()`
9037 
9038 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9039 @*/
9040 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9041 {
9042   PetscFunctionBegin;
9043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9044   PetscValidType(mat, 1);
9045   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9046   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9047   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9048   PetscFunctionReturn(PETSC_SUCCESS);
9049 }
9050 
9051 /*@C
9052    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9053 
9054    Neighbor-wise Collective
9055 
9056    Input Parameters:
9057 +  mat - the factored matrix obtained with `MatGetFactor()`
9058 -  b - the right-hand-side vectors
9059 
9060    Output Parameter:
9061 .  x - the result vectors
9062 
9063    Level: developer
9064 
9065    Note:
9066    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9067    call `MatSolves`(A,x,x).
9068 
9069 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9070 @*/
9071 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9072 {
9073   PetscFunctionBegin;
9074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9075   PetscValidType(mat, 1);
9076   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9077   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9078   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9079 
9080   MatCheckPreallocated(mat, 1);
9081   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9082   PetscUseTypeMethod(mat, solves, b, x);
9083   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9084   PetscFunctionReturn(PETSC_SUCCESS);
9085 }
9086 
9087 /*@
9088    MatIsSymmetric - Test whether a matrix is symmetric
9089 
9090    Collective
9091 
9092    Input Parameters:
9093 +  A - the matrix to test
9094 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9095 
9096    Output Parameters:
9097 .  flg - the result
9098 
9099    Level: intermediate
9100 
9101    Notes:
9102     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9103 
9104     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9105 
9106     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9107     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9108 
9109 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9110           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9111 @*/
9112 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9113 {
9114   PetscFunctionBegin;
9115   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9116   PetscValidBoolPointer(flg, 3);
9117 
9118   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9119   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9120   else {
9121     if (!A->ops->issymmetric) {
9122       MatType mattype;
9123       PetscCall(MatGetType(A, &mattype));
9124       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9125     }
9126     PetscUseTypeMethod(A, issymmetric, tol, flg);
9127     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9128   }
9129   PetscFunctionReturn(PETSC_SUCCESS);
9130 }
9131 
9132 /*@
9133    MatIsHermitian - Test whether a matrix is Hermitian
9134 
9135    Collective
9136 
9137    Input Parameters:
9138 +  A - the matrix to test
9139 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9140 
9141    Output Parameters:
9142 .  flg - the result
9143 
9144    Level: intermediate
9145 
9146    Notes:
9147     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9148 
9149     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9150 
9151     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9152     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9153 
9154 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9155           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9156 @*/
9157 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9158 {
9159   PetscFunctionBegin;
9160   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9161   PetscValidBoolPointer(flg, 3);
9162 
9163   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9164   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9165   else {
9166     if (!A->ops->ishermitian) {
9167       MatType mattype;
9168       PetscCall(MatGetType(A, &mattype));
9169       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9170     }
9171     PetscUseTypeMethod(A, ishermitian, tol, flg);
9172     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9173   }
9174   PetscFunctionReturn(PETSC_SUCCESS);
9175 }
9176 
9177 /*@
9178    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9179 
9180    Not Collective
9181 
9182    Input Parameter:
9183 .  A - the matrix to check
9184 
9185    Output Parameters:
9186 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9187 -  flg - the result (only valid if set is `PETSC_TRUE`)
9188 
9189    Level: advanced
9190 
9191    Notes:
9192    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9193    if you want it explicitly checked
9194 
9195     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9196     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9197 
9198 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9199 @*/
9200 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9201 {
9202   PetscFunctionBegin;
9203   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9204   PetscValidBoolPointer(set, 2);
9205   PetscValidBoolPointer(flg, 3);
9206   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9207     *set = PETSC_TRUE;
9208     *flg = PetscBool3ToBool(A->symmetric);
9209   } else {
9210     *set = PETSC_FALSE;
9211   }
9212   PetscFunctionReturn(PETSC_SUCCESS);
9213 }
9214 
9215 /*@
9216    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9217 
9218    Not Collective
9219 
9220    Input Parameter:
9221 .  A - the matrix to check
9222 
9223    Output Parameters:
9224 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9225 -  flg - the result (only valid if set is `PETSC_TRUE`)
9226 
9227    Level: advanced
9228 
9229    Notes:
9230    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9231 
9232    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9233    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9234 
9235 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9236 @*/
9237 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9238 {
9239   PetscFunctionBegin;
9240   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9241   PetscValidBoolPointer(set, 2);
9242   PetscValidBoolPointer(flg, 3);
9243   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9244     *set = PETSC_TRUE;
9245     *flg = PetscBool3ToBool(A->spd);
9246   } else {
9247     *set = PETSC_FALSE;
9248   }
9249   PetscFunctionReturn(PETSC_SUCCESS);
9250 }
9251 
9252 /*@
9253    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9254 
9255    Not Collective
9256 
9257    Input Parameter:
9258 .  A - the matrix to check
9259 
9260    Output Parameters:
9261 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9262 -  flg - the result (only valid if set is `PETSC_TRUE`)
9263 
9264    Level: advanced
9265 
9266    Notes:
9267    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9268    if you want it explicitly checked
9269 
9270    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9271    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9272 
9273 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9274 @*/
9275 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9276 {
9277   PetscFunctionBegin;
9278   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9279   PetscValidBoolPointer(set, 2);
9280   PetscValidBoolPointer(flg, 3);
9281   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9282     *set = PETSC_TRUE;
9283     *flg = PetscBool3ToBool(A->hermitian);
9284   } else {
9285     *set = PETSC_FALSE;
9286   }
9287   PetscFunctionReturn(PETSC_SUCCESS);
9288 }
9289 
9290 /*@
9291    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9292 
9293    Collective
9294 
9295    Input Parameter:
9296 .  A - the matrix to test
9297 
9298    Output Parameters:
9299 .  flg - the result
9300 
9301    Level: intermediate
9302 
9303    Notes:
9304    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9305 
9306    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
9307    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9308 
9309 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9310 @*/
9311 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9312 {
9313   PetscFunctionBegin;
9314   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9315   PetscValidBoolPointer(flg, 2);
9316   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9317     *flg = PetscBool3ToBool(A->structurally_symmetric);
9318   } else {
9319     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9320     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9321   }
9322   PetscFunctionReturn(PETSC_SUCCESS);
9323 }
9324 
9325 /*@
9326    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9327 
9328    Not Collective
9329 
9330    Input Parameter:
9331 .  A - the matrix to check
9332 
9333    Output Parameters:
9334 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9335 -  flg - the result (only valid if set is PETSC_TRUE)
9336 
9337    Level: advanced
9338 
9339    Notes:
9340    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
9341    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9342 
9343    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9344 
9345 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9346 @*/
9347 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9348 {
9349   PetscFunctionBegin;
9350   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9351   PetscValidBoolPointer(set, 2);
9352   PetscValidBoolPointer(flg, 3);
9353   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9354     *set = PETSC_TRUE;
9355     *flg = PetscBool3ToBool(A->structurally_symmetric);
9356   } else {
9357     *set = PETSC_FALSE;
9358   }
9359   PetscFunctionReturn(PETSC_SUCCESS);
9360 }
9361 
9362 /*@
9363    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9364        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9365 
9366     Not collective
9367 
9368    Input Parameter:
9369 .   mat - the matrix
9370 
9371    Output Parameters:
9372 +   nstash   - the size of the stash
9373 .   reallocs - the number of additional mallocs incurred.
9374 .   bnstash   - the size of the block stash
9375 -   breallocs - the number of additional mallocs incurred.in the block stash
9376 
9377    Level: advanced
9378 
9379 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9380 @*/
9381 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9382 {
9383   PetscFunctionBegin;
9384   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9385   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9386   PetscFunctionReturn(PETSC_SUCCESS);
9387 }
9388 
9389 /*@C
9390    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9391    parallel layout, `PetscLayout` for rows and columns
9392 
9393    Collective
9394 
9395    Input Parameter:
9396 .  mat - the matrix
9397 
9398    Output Parameters:
9399 +   right - (optional) vector that the matrix can be multiplied against
9400 -   left - (optional) vector that the matrix vector product can be stored in
9401 
9402   Level: advanced
9403 
9404    Notes:
9405     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()`.
9406 
9407     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9408 
9409 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9410 @*/
9411 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9412 {
9413   PetscFunctionBegin;
9414   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9415   PetscValidType(mat, 1);
9416   if (mat->ops->getvecs) {
9417     PetscUseTypeMethod(mat, getvecs, right, left);
9418   } else {
9419     PetscInt rbs, cbs;
9420     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9421     if (right) {
9422       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9423       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9424       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9425       PetscCall(VecSetBlockSize(*right, cbs));
9426       PetscCall(VecSetType(*right, mat->defaultvectype));
9427 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9428       if (mat->boundtocpu && mat->bindingpropagates) {
9429         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9430         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9431       }
9432 #endif
9433       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9434     }
9435     if (left) {
9436       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9437       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9438       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9439       PetscCall(VecSetBlockSize(*left, rbs));
9440       PetscCall(VecSetType(*left, mat->defaultvectype));
9441 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9442       if (mat->boundtocpu && mat->bindingpropagates) {
9443         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9444         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9445       }
9446 #endif
9447       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9448     }
9449   }
9450   PetscFunctionReturn(PETSC_SUCCESS);
9451 }
9452 
9453 /*@C
9454    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9455      with default values.
9456 
9457    Not Collective
9458 
9459    Input Parameters:
9460 .    info - the `MatFactorInfo` data structure
9461 
9462    Level: developer
9463 
9464    Notes:
9465     The solvers are generally used through the `KSP` and `PC` objects, for example
9466           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9467 
9468     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9469 
9470    Developer Note:
9471    The Fortran interface is not autogenerated as the
9472    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9473 
9474 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9475 @*/
9476 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9477 {
9478   PetscFunctionBegin;
9479   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9480   PetscFunctionReturn(PETSC_SUCCESS);
9481 }
9482 
9483 /*@
9484    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9485 
9486    Collective
9487 
9488    Input Parameters:
9489 +  mat - the factored matrix
9490 -  is - the index set defining the Schur indices (0-based)
9491 
9492    Level: advanced
9493 
9494    Notes:
9495     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9496 
9497    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9498 
9499    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9500 
9501 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9502           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9503 @*/
9504 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9505 {
9506   PetscErrorCode (*f)(Mat, IS);
9507 
9508   PetscFunctionBegin;
9509   PetscValidType(mat, 1);
9510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9511   PetscValidType(is, 2);
9512   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9513   PetscCheckSameComm(mat, 1, is, 2);
9514   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9515   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9516   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9517   PetscCall(MatDestroy(&mat->schur));
9518   PetscCall((*f)(mat, is));
9519   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9520   PetscFunctionReturn(PETSC_SUCCESS);
9521 }
9522 
9523 /*@
9524   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9525 
9526    Logically Collective
9527 
9528    Input Parameters:
9529 +  F - the factored matrix obtained by calling `MatGetFactor()`
9530 .  S - location where to return the Schur complement, can be `NULL`
9531 -  status - the status of the Schur complement matrix, can be `NULL`
9532 
9533    Level: advanced
9534 
9535    Notes:
9536    You must call `MatFactorSetSchurIS()` before calling this routine.
9537 
9538    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9539 
9540    The routine provides a copy of the Schur matrix stored within the solver data structures.
9541    The caller must destroy the object when it is no longer needed.
9542    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9543 
9544    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)
9545 
9546    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9547 
9548    Developer Note:
9549     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9550    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9551 
9552 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9553 @*/
9554 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9555 {
9556   PetscFunctionBegin;
9557   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9558   if (S) PetscValidPointer(S, 2);
9559   if (status) PetscValidPointer(status, 3);
9560   if (S) {
9561     PetscErrorCode (*f)(Mat, Mat *);
9562 
9563     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9564     if (f) {
9565       PetscCall((*f)(F, S));
9566     } else {
9567       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9568     }
9569   }
9570   if (status) *status = F->schur_status;
9571   PetscFunctionReturn(PETSC_SUCCESS);
9572 }
9573 
9574 /*@
9575   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9576 
9577    Logically Collective
9578 
9579    Input Parameters:
9580 +  F - the factored matrix obtained by calling `MatGetFactor()`
9581 .  *S - location where to return the Schur complement, can be `NULL`
9582 -  status - the status of the Schur complement matrix, can be `NULL`
9583 
9584    Level: advanced
9585 
9586    Notes:
9587    You must call `MatFactorSetSchurIS()` before calling this routine.
9588 
9589    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9590 
9591    The routine returns a the Schur Complement stored within the data structures of the solver.
9592 
9593    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9594 
9595    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9596 
9597    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9598 
9599    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9600 
9601 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9602 @*/
9603 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9604 {
9605   PetscFunctionBegin;
9606   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9607   if (S) PetscValidPointer(S, 2);
9608   if (status) PetscValidPointer(status, 3);
9609   if (S) *S = F->schur;
9610   if (status) *status = F->schur_status;
9611   PetscFunctionReturn(PETSC_SUCCESS);
9612 }
9613 
9614 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9615 {
9616   Mat S = F->schur;
9617 
9618   PetscFunctionBegin;
9619   switch (F->schur_status) {
9620   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9621   case MAT_FACTOR_SCHUR_INVERTED:
9622     if (S) {
9623       S->ops->solve             = NULL;
9624       S->ops->matsolve          = NULL;
9625       S->ops->solvetranspose    = NULL;
9626       S->ops->matsolvetranspose = NULL;
9627       S->ops->solveadd          = NULL;
9628       S->ops->solvetransposeadd = NULL;
9629       S->factortype             = MAT_FACTOR_NONE;
9630       PetscCall(PetscFree(S->solvertype));
9631     }
9632   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9633     break;
9634   default:
9635     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9636   }
9637   PetscFunctionReturn(PETSC_SUCCESS);
9638 }
9639 
9640 /*@
9641   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9642 
9643    Logically Collective
9644 
9645    Input Parameters:
9646 +  F - the factored matrix obtained by calling `MatGetFactor()`
9647 .  *S - location where the Schur complement is stored
9648 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9649 
9650    Level: advanced
9651 
9652 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9653 @*/
9654 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9655 {
9656   PetscFunctionBegin;
9657   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9658   if (S) {
9659     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9660     *S = NULL;
9661   }
9662   F->schur_status = status;
9663   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9664   PetscFunctionReturn(PETSC_SUCCESS);
9665 }
9666 
9667 /*@
9668   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9669 
9670    Logically Collective
9671 
9672    Input Parameters:
9673 +  F - the factored matrix obtained by calling `MatGetFactor()`
9674 .  rhs - location where the right hand side of the Schur complement system is stored
9675 -  sol - location where the solution of the Schur complement system has to be returned
9676 
9677    Level: advanced
9678 
9679    Notes:
9680    The sizes of the vectors should match the size of the Schur complement
9681 
9682    Must be called after `MatFactorSetSchurIS()`
9683 
9684 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9685 @*/
9686 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9687 {
9688   PetscFunctionBegin;
9689   PetscValidType(F, 1);
9690   PetscValidType(rhs, 2);
9691   PetscValidType(sol, 3);
9692   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9693   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9694   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9695   PetscCheckSameComm(F, 1, rhs, 2);
9696   PetscCheckSameComm(F, 1, sol, 3);
9697   PetscCall(MatFactorFactorizeSchurComplement(F));
9698   switch (F->schur_status) {
9699   case MAT_FACTOR_SCHUR_FACTORED:
9700     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9701     break;
9702   case MAT_FACTOR_SCHUR_INVERTED:
9703     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9704     break;
9705   default:
9706     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9707   }
9708   PetscFunctionReturn(PETSC_SUCCESS);
9709 }
9710 
9711 /*@
9712   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9713 
9714    Logically Collective
9715 
9716    Input Parameters:
9717 +  F - the factored matrix obtained by calling `MatGetFactor()`
9718 .  rhs - location where the right hand side of the Schur complement system is stored
9719 -  sol - location where the solution of the Schur complement system has to be returned
9720 
9721    Level: advanced
9722 
9723    Notes:
9724    The sizes of the vectors should match the size of the Schur complement
9725 
9726    Must be called after `MatFactorSetSchurIS()`
9727 
9728 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9729 @*/
9730 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9731 {
9732   PetscFunctionBegin;
9733   PetscValidType(F, 1);
9734   PetscValidType(rhs, 2);
9735   PetscValidType(sol, 3);
9736   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9737   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9738   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9739   PetscCheckSameComm(F, 1, rhs, 2);
9740   PetscCheckSameComm(F, 1, sol, 3);
9741   PetscCall(MatFactorFactorizeSchurComplement(F));
9742   switch (F->schur_status) {
9743   case MAT_FACTOR_SCHUR_FACTORED:
9744     PetscCall(MatSolve(F->schur, rhs, sol));
9745     break;
9746   case MAT_FACTOR_SCHUR_INVERTED:
9747     PetscCall(MatMult(F->schur, rhs, sol));
9748     break;
9749   default:
9750     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9751   }
9752   PetscFunctionReturn(PETSC_SUCCESS);
9753 }
9754 
9755 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9756 #if PetscDefined(HAVE_CUDA)
9757 PETSC_EXTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Private(Mat);
9758 #endif
9759 
9760 /* Schur status updated in the interface */
9761 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9762 {
9763   Mat S = F->schur;
9764 
9765   PetscFunctionBegin;
9766   if (S) {
9767     PetscMPIInt size;
9768     PetscBool   isdense, isdensecuda;
9769 
9770     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9771     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9772     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9773     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9774     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9775     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9776     if (isdense) {
9777       PetscCall(MatSeqDenseInvertFactors_Private(S));
9778     } else if (isdensecuda) {
9779 #if defined(PETSC_HAVE_CUDA)
9780       PetscCall(MatSeqDenseCUDAInvertFactors_Private(S));
9781 #endif
9782     }
9783     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9784   }
9785   PetscFunctionReturn(PETSC_SUCCESS);
9786 }
9787 
9788 /*@
9789   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9790 
9791    Logically Collective
9792 
9793    Input Parameters:
9794 .  F - the factored matrix obtained by calling `MatGetFactor()`
9795 
9796    Level: advanced
9797 
9798    Notes:
9799     Must be called after `MatFactorSetSchurIS()`.
9800 
9801    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9802 
9803 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9804 @*/
9805 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9806 {
9807   PetscFunctionBegin;
9808   PetscValidType(F, 1);
9809   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9810   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9811   PetscCall(MatFactorFactorizeSchurComplement(F));
9812   PetscCall(MatFactorInvertSchurComplement_Private(F));
9813   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9814   PetscFunctionReturn(PETSC_SUCCESS);
9815 }
9816 
9817 /*@
9818   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9819 
9820    Logically Collective
9821 
9822    Input Parameters:
9823 .  F - the factored matrix obtained by calling `MatGetFactor()`
9824 
9825    Level: advanced
9826 
9827    Note:
9828     Must be called after `MatFactorSetSchurIS()`
9829 
9830 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9831 @*/
9832 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9833 {
9834   MatFactorInfo info;
9835 
9836   PetscFunctionBegin;
9837   PetscValidType(F, 1);
9838   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9839   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9840   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9841   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9842     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9843   } else {
9844     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9845   }
9846   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9847   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9848   PetscFunctionReturn(PETSC_SUCCESS);
9849 }
9850 
9851 /*@
9852    MatPtAP - Creates the matrix product C = P^T * A * P
9853 
9854    Neighbor-wise Collective
9855 
9856    Input Parameters:
9857 +  A - the matrix
9858 .  P - the projection matrix
9859 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9860 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9861           if the result is a dense matrix this is irrelevant
9862 
9863    Output Parameters:
9864 .  C - the product matrix
9865 
9866    Level: intermediate
9867 
9868    Notes:
9869    C will be created and must be destroyed by the user with `MatDestroy()`.
9870 
9871    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9872 
9873    Developer Note:
9874    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9875 
9876 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9877 @*/
9878 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9879 {
9880   PetscFunctionBegin;
9881   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9882   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9883 
9884   if (scall == MAT_INITIAL_MATRIX) {
9885     PetscCall(MatProductCreate(A, P, NULL, C));
9886     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9887     PetscCall(MatProductSetAlgorithm(*C, "default"));
9888     PetscCall(MatProductSetFill(*C, fill));
9889 
9890     (*C)->product->api_user = PETSC_TRUE;
9891     PetscCall(MatProductSetFromOptions(*C));
9892     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);
9893     PetscCall(MatProductSymbolic(*C));
9894   } else { /* scall == MAT_REUSE_MATRIX */
9895     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9896   }
9897 
9898   PetscCall(MatProductNumeric(*C));
9899   (*C)->symmetric = A->symmetric;
9900   (*C)->spd       = A->spd;
9901   PetscFunctionReturn(PETSC_SUCCESS);
9902 }
9903 
9904 /*@
9905    MatRARt - Creates the matrix product C = R * A * R^T
9906 
9907    Neighbor-wise Collective
9908 
9909    Input Parameters:
9910 +  A - the matrix
9911 .  R - the projection matrix
9912 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9913 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9914           if the result is a dense matrix this is irrelevant
9915 
9916    Output Parameters:
9917 .  C - the product matrix
9918 
9919    Level: intermediate
9920 
9921    Notes:
9922    C will be created and must be destroyed by the user with `MatDestroy()`.
9923 
9924    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9925 
9926    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9927    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9928    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9929    We recommend using MatPtAP().
9930 
9931 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9932 @*/
9933 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9934 {
9935   PetscFunctionBegin;
9936   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9937   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9938 
9939   if (scall == MAT_INITIAL_MATRIX) {
9940     PetscCall(MatProductCreate(A, R, NULL, C));
9941     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9942     PetscCall(MatProductSetAlgorithm(*C, "default"));
9943     PetscCall(MatProductSetFill(*C, fill));
9944 
9945     (*C)->product->api_user = PETSC_TRUE;
9946     PetscCall(MatProductSetFromOptions(*C));
9947     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);
9948     PetscCall(MatProductSymbolic(*C));
9949   } else { /* scall == MAT_REUSE_MATRIX */
9950     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9951   }
9952 
9953   PetscCall(MatProductNumeric(*C));
9954   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9955   PetscFunctionReturn(PETSC_SUCCESS);
9956 }
9957 
9958 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9959 {
9960   PetscFunctionBegin;
9961   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9962 
9963   if (scall == MAT_INITIAL_MATRIX) {
9964     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9965     PetscCall(MatProductCreate(A, B, NULL, C));
9966     PetscCall(MatProductSetType(*C, ptype));
9967     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9968     PetscCall(MatProductSetFill(*C, fill));
9969 
9970     (*C)->product->api_user = PETSC_TRUE;
9971     PetscCall(MatProductSetFromOptions(*C));
9972     PetscCall(MatProductSymbolic(*C));
9973   } else { /* scall == MAT_REUSE_MATRIX */
9974     Mat_Product *product = (*C)->product;
9975     PetscBool    isdense;
9976 
9977     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9978     if (isdense && product && product->type != ptype) {
9979       PetscCall(MatProductClear(*C));
9980       product = NULL;
9981     }
9982     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9983     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9984       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9985       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9986       product           = (*C)->product;
9987       product->fill     = fill;
9988       product->api_user = PETSC_TRUE;
9989       product->clear    = PETSC_TRUE;
9990 
9991       PetscCall(MatProductSetType(*C, ptype));
9992       PetscCall(MatProductSetFromOptions(*C));
9993       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);
9994       PetscCall(MatProductSymbolic(*C));
9995     } else { /* user may change input matrices A or B when REUSE */
9996       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9997     }
9998   }
9999   PetscCall(MatProductNumeric(*C));
10000   PetscFunctionReturn(PETSC_SUCCESS);
10001 }
10002 
10003 /*@
10004    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10005 
10006    Neighbor-wise Collective
10007 
10008    Input Parameters:
10009 +  A - the left matrix
10010 .  B - the right matrix
10011 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10012 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10013           if the result is a dense matrix this is irrelevant
10014 
10015    Output Parameters:
10016 .  C - the product matrix
10017 
10018    Notes:
10019    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10020 
10021    `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
10022    call to this function with `MAT_INITIAL_MATRIX`.
10023 
10024    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10025 
10026    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`,
10027    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10028 
10029    Example of Usage:
10030 .vb
10031      MatProductCreate(A,B,NULL,&C);
10032      MatProductSetType(C,MATPRODUCT_AB);
10033      MatProductSymbolic(C);
10034      MatProductNumeric(C); // compute C=A * B
10035      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10036      MatProductNumeric(C);
10037      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10038      MatProductNumeric(C);
10039 .ve
10040 
10041    Level: intermediate
10042 
10043 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10044 @*/
10045 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10046 {
10047   PetscFunctionBegin;
10048   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10049   PetscFunctionReturn(PETSC_SUCCESS);
10050 }
10051 
10052 /*@
10053    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10054 
10055    Neighbor-wise Collective
10056 
10057    Input Parameters:
10058 +  A - the left matrix
10059 .  B - the right matrix
10060 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10061 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10062 
10063    Output Parameters:
10064 .  C - the product matrix
10065 
10066    Level: intermediate
10067 
10068    Notes:
10069    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10070 
10071    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10072 
10073    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10074    actually needed.
10075 
10076    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10077    and for pairs of `MATMPIDENSE` matrices.
10078 
10079    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10080 
10081    Options Database Keys:
10082 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10083               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10084               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10085 
10086 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10087 @*/
10088 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10089 {
10090   PetscFunctionBegin;
10091   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10092   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10093   PetscFunctionReturn(PETSC_SUCCESS);
10094 }
10095 
10096 /*@
10097    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10098 
10099    Neighbor-wise Collective
10100 
10101    Input Parameters:
10102 +  A - the left matrix
10103 .  B - the right matrix
10104 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10105 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10106 
10107    Output Parameters:
10108 .  C - the product matrix
10109 
10110    Level: intermediate
10111 
10112    Notes:
10113    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10114 
10115    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10116 
10117    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10118 
10119    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10120    actually needed.
10121 
10122    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10123    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10124 
10125 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10126 @*/
10127 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10128 {
10129   PetscFunctionBegin;
10130   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10131   PetscFunctionReturn(PETSC_SUCCESS);
10132 }
10133 
10134 /*@
10135    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10136 
10137    Neighbor-wise Collective
10138 
10139    Input Parameters:
10140 +  A - the left matrix
10141 .  B - the middle matrix
10142 .  C - the right matrix
10143 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10144 -  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
10145           if the result is a dense matrix this is irrelevant
10146 
10147    Output Parameters:
10148 .  D - the product matrix
10149 
10150    Level: intermediate
10151 
10152    Notes:
10153    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10154 
10155    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10156 
10157    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10158 
10159    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10160    actually needed.
10161 
10162    If you have many matrices with the same non-zero structure to multiply, you
10163    should use `MAT_REUSE_MATRIX` in all calls but the first
10164 
10165 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10166 @*/
10167 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10168 {
10169   PetscFunctionBegin;
10170   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10171   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10172 
10173   if (scall == MAT_INITIAL_MATRIX) {
10174     PetscCall(MatProductCreate(A, B, C, D));
10175     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10176     PetscCall(MatProductSetAlgorithm(*D, "default"));
10177     PetscCall(MatProductSetFill(*D, fill));
10178 
10179     (*D)->product->api_user = PETSC_TRUE;
10180     PetscCall(MatProductSetFromOptions(*D));
10181     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,
10182                ((PetscObject)C)->type_name);
10183     PetscCall(MatProductSymbolic(*D));
10184   } else { /* user may change input matrices when REUSE */
10185     PetscCall(MatProductReplaceMats(A, B, C, *D));
10186   }
10187   PetscCall(MatProductNumeric(*D));
10188   PetscFunctionReturn(PETSC_SUCCESS);
10189 }
10190 
10191 /*@
10192    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10193 
10194    Collective
10195 
10196    Input Parameters:
10197 +  mat - the matrix
10198 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10199 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10200 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10201 
10202    Output Parameter:
10203 .  matredundant - redundant matrix
10204 
10205    Level: advanced
10206 
10207    Notes:
10208    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10209    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10210 
10211    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10212    calling it.
10213 
10214    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10215 
10216 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10217 @*/
10218 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10219 {
10220   MPI_Comm       comm;
10221   PetscMPIInt    size;
10222   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10223   Mat_Redundant *redund     = NULL;
10224   PetscSubcomm   psubcomm   = NULL;
10225   MPI_Comm       subcomm_in = subcomm;
10226   Mat           *matseq;
10227   IS             isrow, iscol;
10228   PetscBool      newsubcomm = PETSC_FALSE;
10229 
10230   PetscFunctionBegin;
10231   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10232   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10233     PetscValidPointer(*matredundant, 5);
10234     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10235   }
10236 
10237   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10238   if (size == 1 || nsubcomm == 1) {
10239     if (reuse == MAT_INITIAL_MATRIX) {
10240       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10241     } else {
10242       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");
10243       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10244     }
10245     PetscFunctionReturn(PETSC_SUCCESS);
10246   }
10247 
10248   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10249   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10250   MatCheckPreallocated(mat, 1);
10251 
10252   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10253   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10254     /* create psubcomm, then get subcomm */
10255     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10256     PetscCallMPI(MPI_Comm_size(comm, &size));
10257     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10258 
10259     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10260     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10261     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10262     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10263     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10264     newsubcomm = PETSC_TRUE;
10265     PetscCall(PetscSubcommDestroy(&psubcomm));
10266   }
10267 
10268   /* get isrow, iscol and a local sequential matrix matseq[0] */
10269   if (reuse == MAT_INITIAL_MATRIX) {
10270     mloc_sub = PETSC_DECIDE;
10271     nloc_sub = PETSC_DECIDE;
10272     if (bs < 1) {
10273       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10274       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10275     } else {
10276       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10277       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10278     }
10279     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10280     rstart = rend - mloc_sub;
10281     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10282     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10283   } else { /* reuse == MAT_REUSE_MATRIX */
10284     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");
10285     /* retrieve subcomm */
10286     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10287     redund = (*matredundant)->redundant;
10288     isrow  = redund->isrow;
10289     iscol  = redund->iscol;
10290     matseq = redund->matseq;
10291   }
10292   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10293 
10294   /* get matredundant over subcomm */
10295   if (reuse == MAT_INITIAL_MATRIX) {
10296     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10297 
10298     /* create a supporting struct and attach it to C for reuse */
10299     PetscCall(PetscNew(&redund));
10300     (*matredundant)->redundant = redund;
10301     redund->isrow              = isrow;
10302     redund->iscol              = iscol;
10303     redund->matseq             = matseq;
10304     if (newsubcomm) {
10305       redund->subcomm = subcomm;
10306     } else {
10307       redund->subcomm = MPI_COMM_NULL;
10308     }
10309   } else {
10310     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10311   }
10312 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10313   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10314     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10315     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10316   }
10317 #endif
10318   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10319   PetscFunctionReturn(PETSC_SUCCESS);
10320 }
10321 
10322 /*@C
10323    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10324    a given `Mat`. Each submatrix can span multiple procs.
10325 
10326    Collective
10327 
10328    Input Parameters:
10329 +  mat - the matrix
10330 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10331 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10332 
10333    Output Parameter:
10334 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10335 
10336   Level: advanced
10337 
10338   Notes:
10339   The submatrix partition across processors is dictated by `subComm` a
10340   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10341   is not restricted to be grouped with consecutive original ranks.
10342 
10343   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10344   map directly to the layout of the original matrix [wrt the local
10345   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10346   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10347   the `subMat`. However the offDiagMat looses some columns - and this is
10348   reconstructed with `MatSetValues()`
10349 
10350   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10351 
10352 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10353 @*/
10354 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10355 {
10356   PetscMPIInt commsize, subCommSize;
10357 
10358   PetscFunctionBegin;
10359   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10360   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10361   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10362 
10363   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");
10364   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10365   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10366   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10367   PetscFunctionReturn(PETSC_SUCCESS);
10368 }
10369 
10370 /*@
10371    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10372 
10373    Not Collective
10374 
10375    Input Parameters:
10376 +  mat - matrix to extract local submatrix from
10377 .  isrow - local row indices for submatrix
10378 -  iscol - local column indices for submatrix
10379 
10380    Output Parameter:
10381 .  submat - the submatrix
10382 
10383    Level: intermediate
10384 
10385    Notes:
10386    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10387 
10388    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10389    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10390 
10391    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10392    `MatSetValuesBlockedLocal()` will also be implemented.
10393 
10394    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10395    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10396 
10397 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10398 @*/
10399 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10400 {
10401   PetscFunctionBegin;
10402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10403   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10404   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10405   PetscCheckSameComm(isrow, 2, iscol, 3);
10406   PetscValidPointer(submat, 4);
10407   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10408 
10409   if (mat->ops->getlocalsubmatrix) {
10410     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10411   } else {
10412     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10413   }
10414   PetscFunctionReturn(PETSC_SUCCESS);
10415 }
10416 
10417 /*@
10418    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10419 
10420    Not Collective
10421 
10422    Input Parameters:
10423 +  mat - matrix to extract local submatrix from
10424 .  isrow - local row indices for submatrix
10425 .  iscol - local column indices for submatrix
10426 -  submat - the submatrix
10427 
10428    Level: intermediate
10429 
10430 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10431 @*/
10432 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10433 {
10434   PetscFunctionBegin;
10435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10436   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10437   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10438   PetscCheckSameComm(isrow, 2, iscol, 3);
10439   PetscValidPointer(submat, 4);
10440   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10441 
10442   if (mat->ops->restorelocalsubmatrix) {
10443     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10444   } else {
10445     PetscCall(MatDestroy(submat));
10446   }
10447   *submat = NULL;
10448   PetscFunctionReturn(PETSC_SUCCESS);
10449 }
10450 
10451 /*@
10452    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10453 
10454    Collective
10455 
10456    Input Parameter:
10457 .  mat - the matrix
10458 
10459    Output Parameter:
10460 .  is - if any rows have zero diagonals this contains the list of them
10461 
10462    Level: developer
10463 
10464 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10465 @*/
10466 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10467 {
10468   PetscFunctionBegin;
10469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10470   PetscValidType(mat, 1);
10471   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10472   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10473 
10474   if (!mat->ops->findzerodiagonals) {
10475     Vec                diag;
10476     const PetscScalar *a;
10477     PetscInt          *rows;
10478     PetscInt           rStart, rEnd, r, nrow = 0;
10479 
10480     PetscCall(MatCreateVecs(mat, &diag, NULL));
10481     PetscCall(MatGetDiagonal(mat, diag));
10482     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10483     PetscCall(VecGetArrayRead(diag, &a));
10484     for (r = 0; r < rEnd - rStart; ++r)
10485       if (a[r] == 0.0) ++nrow;
10486     PetscCall(PetscMalloc1(nrow, &rows));
10487     nrow = 0;
10488     for (r = 0; r < rEnd - rStart; ++r)
10489       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10490     PetscCall(VecRestoreArrayRead(diag, &a));
10491     PetscCall(VecDestroy(&diag));
10492     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10493   } else {
10494     PetscUseTypeMethod(mat, findzerodiagonals, is);
10495   }
10496   PetscFunctionReturn(PETSC_SUCCESS);
10497 }
10498 
10499 /*@
10500    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10501 
10502    Collective
10503 
10504    Input Parameter:
10505 .  mat - the matrix
10506 
10507    Output Parameter:
10508 .  is - contains the list of rows with off block diagonal entries
10509 
10510    Level: developer
10511 
10512 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10513 @*/
10514 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10515 {
10516   PetscFunctionBegin;
10517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10518   PetscValidType(mat, 1);
10519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10520   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10521 
10522   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10523   PetscFunctionReturn(PETSC_SUCCESS);
10524 }
10525 
10526 /*@C
10527   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10528 
10529   Collective; No Fortran Support
10530 
10531   Input Parameters:
10532 . mat - the matrix
10533 
10534   Output Parameters:
10535 . values - the block inverses in column major order (FORTRAN-like)
10536 
10537   Level: advanced
10538 
10539    Notes:
10540    The size of the blocks is determined by the block size of the matrix.
10541 
10542    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10543 
10544    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10545 
10546 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10547 @*/
10548 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10549 {
10550   PetscFunctionBegin;
10551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10552   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10553   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10554   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10555   PetscFunctionReturn(PETSC_SUCCESS);
10556 }
10557 
10558 /*@C
10559   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10560 
10561   Collective; No Fortran Support
10562 
10563   Input Parameters:
10564 + mat - the matrix
10565 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10566 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10567 
10568   Output Parameters:
10569 . values - the block inverses in column major order (FORTRAN-like)
10570 
10571   Level: advanced
10572 
10573   Notes:
10574   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10575 
10576   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10577 
10578 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10579 @*/
10580 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10581 {
10582   PetscFunctionBegin;
10583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10584   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10585   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10586   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10587   PetscFunctionReturn(PETSC_SUCCESS);
10588 }
10589 
10590 /*@
10591   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10592 
10593   Collective
10594 
10595   Input Parameters:
10596 + A - the matrix
10597 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10598 
10599   Level: advanced
10600 
10601   Note:
10602   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10603 
10604 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10605 @*/
10606 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10607 {
10608   const PetscScalar *vals;
10609   PetscInt          *dnnz;
10610   PetscInt           m, rstart, rend, bs, i, j;
10611 
10612   PetscFunctionBegin;
10613   PetscCall(MatInvertBlockDiagonal(A, &vals));
10614   PetscCall(MatGetBlockSize(A, &bs));
10615   PetscCall(MatGetLocalSize(A, &m, NULL));
10616   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10617   PetscCall(PetscMalloc1(m / bs, &dnnz));
10618   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10619   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10620   PetscCall(PetscFree(dnnz));
10621   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10622   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10623   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10624   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10625   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10626   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10627   PetscFunctionReturn(PETSC_SUCCESS);
10628 }
10629 
10630 /*@C
10631     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10632     via `MatTransposeColoringCreate()`.
10633 
10634     Collective
10635 
10636     Input Parameter:
10637 .   c - coloring context
10638 
10639     Level: intermediate
10640 
10641 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10642 @*/
10643 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10644 {
10645   MatTransposeColoring matcolor = *c;
10646 
10647   PetscFunctionBegin;
10648   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10649   if (--((PetscObject)matcolor)->refct > 0) {
10650     matcolor = NULL;
10651     PetscFunctionReturn(PETSC_SUCCESS);
10652   }
10653 
10654   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10655   PetscCall(PetscFree(matcolor->rows));
10656   PetscCall(PetscFree(matcolor->den2sp));
10657   PetscCall(PetscFree(matcolor->colorforcol));
10658   PetscCall(PetscFree(matcolor->columns));
10659   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10660   PetscCall(PetscHeaderDestroy(c));
10661   PetscFunctionReturn(PETSC_SUCCESS);
10662 }
10663 
10664 /*@C
10665     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10666     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10667     `MatTransposeColoring` to sparse B.
10668 
10669     Collective
10670 
10671     Input Parameters:
10672 +   B - sparse matrix B
10673 .   Btdense - symbolic dense matrix B^T
10674 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10675 
10676     Output Parameter:
10677 .   Btdense - dense matrix B^T
10678 
10679     Level: developer
10680 
10681     Note:
10682     These are used internally for some implementations of `MatRARt()`
10683 
10684 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10685 @*/
10686 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10687 {
10688   PetscFunctionBegin;
10689   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10690   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10691   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10692 
10693   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10694   PetscFunctionReturn(PETSC_SUCCESS);
10695 }
10696 
10697 /*@C
10698     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10699     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10700     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10701     Csp from Cden.
10702 
10703     Collective
10704 
10705     Input Parameters:
10706 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10707 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10708 
10709     Output Parameter:
10710 .   Csp - sparse matrix
10711 
10712     Level: developer
10713 
10714     Note:
10715     These are used internally for some implementations of `MatRARt()`
10716 
10717 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10718 @*/
10719 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10720 {
10721   PetscFunctionBegin;
10722   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10723   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10724   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10725 
10726   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10727   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10728   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10729   PetscFunctionReturn(PETSC_SUCCESS);
10730 }
10731 
10732 /*@C
10733    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10734 
10735    Collective
10736 
10737    Input Parameters:
10738 +  mat - the matrix product C
10739 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10740 
10741     Output Parameter:
10742 .   color - the new coloring context
10743 
10744     Level: intermediate
10745 
10746 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10747           `MatTransColoringApplyDenToSp()`
10748 @*/
10749 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10750 {
10751   MatTransposeColoring c;
10752   MPI_Comm             comm;
10753 
10754   PetscFunctionBegin;
10755   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10756   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10757   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10758 
10759   c->ctype = iscoloring->ctype;
10760   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10761 
10762   *color = c;
10763   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10764   PetscFunctionReturn(PETSC_SUCCESS);
10765 }
10766 
10767 /*@
10768       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10769         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10770         same, otherwise it will be larger
10771 
10772      Not Collective
10773 
10774   Input Parameter:
10775 .    A  - the matrix
10776 
10777   Output Parameter:
10778 .    state - the current state
10779 
10780   Level: intermediate
10781 
10782   Notes:
10783     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10784          different matrices
10785 
10786     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10787 
10788     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10789 
10790 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10791 @*/
10792 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10793 {
10794   PetscFunctionBegin;
10795   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10796   *state = mat->nonzerostate;
10797   PetscFunctionReturn(PETSC_SUCCESS);
10798 }
10799 
10800 /*@
10801       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10802                  matrices from each processor
10803 
10804     Collective
10805 
10806    Input Parameters:
10807 +    comm - the communicators the parallel matrix will live on
10808 .    seqmat - the input sequential matrices
10809 .    n - number of local columns (or `PETSC_DECIDE`)
10810 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10811 
10812    Output Parameter:
10813 .    mpimat - the parallel matrix generated
10814 
10815     Level: developer
10816 
10817    Note:
10818     The number of columns of the matrix in EACH processor MUST be the same.
10819 
10820 .seealso: [](chapter_matrices), `Mat`
10821 @*/
10822 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10823 {
10824   PetscMPIInt size;
10825 
10826   PetscFunctionBegin;
10827   PetscCallMPI(MPI_Comm_size(comm, &size));
10828   if (size == 1) {
10829     if (reuse == MAT_INITIAL_MATRIX) {
10830       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10831     } else {
10832       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10833     }
10834     PetscFunctionReturn(PETSC_SUCCESS);
10835   }
10836 
10837   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");
10838 
10839   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10840   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10841   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10842   PetscFunctionReturn(PETSC_SUCCESS);
10843 }
10844 
10845 /*@
10846      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10847 
10848     Collective
10849 
10850    Input Parameters:
10851 +    A   - the matrix to create subdomains from
10852 -    N   - requested number of subdomains
10853 
10854    Output Parameters:
10855 +    n   - number of subdomains resulting on this rank
10856 -    iss - `IS` list with indices of subdomains on this rank
10857 
10858     Level: advanced
10859 
10860     Note:
10861     The number of subdomains must be smaller than the communicator size
10862 
10863 .seealso: [](chapter_matrices), `Mat`, `IS`
10864 @*/
10865 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10866 {
10867   MPI_Comm    comm, subcomm;
10868   PetscMPIInt size, rank, color;
10869   PetscInt    rstart, rend, k;
10870 
10871   PetscFunctionBegin;
10872   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10873   PetscCallMPI(MPI_Comm_size(comm, &size));
10874   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10875   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);
10876   *n    = 1;
10877   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10878   color = rank / k;
10879   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10880   PetscCall(PetscMalloc1(1, iss));
10881   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10882   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10883   PetscCallMPI(MPI_Comm_free(&subcomm));
10884   PetscFunctionReturn(PETSC_SUCCESS);
10885 }
10886 
10887 /*@
10888    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10889 
10890    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10891    If they are not the same, uses `MatMatMatMult()`.
10892 
10893    Once the coarse grid problem is constructed, correct for interpolation operators
10894    that are not of full rank, which can legitimately happen in the case of non-nested
10895    geometric multigrid.
10896 
10897    Input Parameters:
10898 +  restrct - restriction operator
10899 .  dA - fine grid matrix
10900 .  interpolate - interpolation operator
10901 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10902 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10903 
10904    Output Parameters:
10905 .  A - the Galerkin coarse matrix
10906 
10907    Options Database Key:
10908 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10909 
10910    Level: developer
10911 
10912 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10913 @*/
10914 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10915 {
10916   IS  zerorows;
10917   Vec diag;
10918 
10919   PetscFunctionBegin;
10920   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10921   /* Construct the coarse grid matrix */
10922   if (interpolate == restrct) {
10923     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10924   } else {
10925     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10926   }
10927 
10928   /* If the interpolation matrix is not of full rank, A will have zero rows.
10929      This can legitimately happen in the case of non-nested geometric multigrid.
10930      In that event, we set the rows of the matrix to the rows of the identity,
10931      ignoring the equations (as the RHS will also be zero). */
10932 
10933   PetscCall(MatFindZeroRows(*A, &zerorows));
10934 
10935   if (zerorows != NULL) { /* if there are any zero rows */
10936     PetscCall(MatCreateVecs(*A, &diag, NULL));
10937     PetscCall(MatGetDiagonal(*A, diag));
10938     PetscCall(VecISSet(diag, zerorows, 1.0));
10939     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10940     PetscCall(VecDestroy(&diag));
10941     PetscCall(ISDestroy(&zerorows));
10942   }
10943   PetscFunctionReturn(PETSC_SUCCESS);
10944 }
10945 
10946 /*@C
10947     MatSetOperation - Allows user to set a matrix operation for any matrix type
10948 
10949    Logically Collective
10950 
10951     Input Parameters:
10952 +   mat - the matrix
10953 .   op - the name of the operation
10954 -   f - the function that provides the operation
10955 
10956    Level: developer
10957 
10958     Usage:
10959 .vb
10960   extern PetscErrorCode usermult(Mat, Vec, Vec);
10961 
10962   PetscCall(MatCreateXXX(comm, ..., &A));
10963   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10964 .ve
10965 
10966     Notes:
10967     See the file `include/petscmat.h` for a complete list of matrix
10968     operations, which all have the form MATOP_<OPERATION>, where
10969     <OPERATION> is the name (in all capital letters) of the
10970     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10971 
10972     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10973     sequence as the usual matrix interface routines, since they
10974     are intended to be accessed via the usual matrix interface
10975     routines, e.g.,
10976 .vb
10977   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10978 .ve
10979 
10980     In particular each function MUST return `PETSC_SUCCESS` on success and
10981     nonzero on failure.
10982 
10983     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10984 
10985 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10986 @*/
10987 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10988 {
10989   PetscFunctionBegin;
10990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10991   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10992   (((void (**)(void))mat->ops)[op]) = f;
10993   PetscFunctionReturn(PETSC_SUCCESS);
10994 }
10995 
10996 /*@C
10997     MatGetOperation - Gets a matrix operation for any matrix type.
10998 
10999     Not Collective
11000 
11001     Input Parameters:
11002 +   mat - the matrix
11003 -   op - the name of the operation
11004 
11005     Output Parameter:
11006 .   f - the function that provides the operation
11007 
11008     Level: developer
11009 
11010     Usage:
11011 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
11012 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
11013 
11014     Notes:
11015     See the file include/petscmat.h for a complete list of matrix
11016     operations, which all have the form MATOP_<OPERATION>, where
11017     <OPERATION> is the name (in all capital letters) of the
11018     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11019 
11020     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11021 
11022 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11023 @*/
11024 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11025 {
11026   PetscFunctionBegin;
11027   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11028   *f = (((void (**)(void))mat->ops)[op]);
11029   PetscFunctionReturn(PETSC_SUCCESS);
11030 }
11031 
11032 /*@
11033     MatHasOperation - Determines whether the given matrix supports the particular operation.
11034 
11035    Not Collective
11036 
11037    Input Parameters:
11038 +  mat - the matrix
11039 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11040 
11041    Output Parameter:
11042 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11043 
11044    Level: advanced
11045 
11046    Note:
11047    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11048 
11049 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11050 @*/
11051 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11052 {
11053   PetscFunctionBegin;
11054   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11055   PetscValidBoolPointer(has, 3);
11056   if (mat->ops->hasoperation) {
11057     PetscUseTypeMethod(mat, hasoperation, op, has);
11058   } else {
11059     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11060     else {
11061       *has = PETSC_FALSE;
11062       if (op == MATOP_CREATE_SUBMATRIX) {
11063         PetscMPIInt size;
11064 
11065         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11066         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11067       }
11068     }
11069   }
11070   PetscFunctionReturn(PETSC_SUCCESS);
11071 }
11072 
11073 /*@
11074     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11075 
11076    Collective
11077 
11078    Input Parameters:
11079 .  mat - the matrix
11080 
11081    Output Parameter:
11082 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11083 
11084    Level: beginner
11085 
11086 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11087 @*/
11088 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11089 {
11090   PetscFunctionBegin;
11091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11092   PetscValidType(mat, 1);
11093   PetscValidBoolPointer(cong, 2);
11094   if (!mat->rmap || !mat->cmap) {
11095     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11096     PetscFunctionReturn(PETSC_SUCCESS);
11097   }
11098   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11099     PetscCall(PetscLayoutSetUp(mat->rmap));
11100     PetscCall(PetscLayoutSetUp(mat->cmap));
11101     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11102     if (*cong) mat->congruentlayouts = 1;
11103     else mat->congruentlayouts = 0;
11104   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11105   PetscFunctionReturn(PETSC_SUCCESS);
11106 }
11107 
11108 PetscErrorCode MatSetInf(Mat A)
11109 {
11110   PetscFunctionBegin;
11111   PetscUseTypeMethod(A, setinf);
11112   PetscFunctionReturn(PETSC_SUCCESS);
11113 }
11114 
11115 /*@C
11116    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
11117    and possibly removes small values from the graph structure.
11118 
11119    Collective
11120 
11121    Input Parameters:
11122 +  A - the matrix
11123 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11124 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11125 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11126 
11127    Output Parameter:
11128 .  graph - the resulting graph
11129 
11130    Level: advanced
11131 
11132 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11133 @*/
11134 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11135 {
11136   PetscFunctionBegin;
11137   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11138   PetscValidType(A, 1);
11139   PetscValidLogicalCollectiveBool(A, scale, 3);
11140   PetscValidPointer(graph, 5);
11141   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11142   PetscFunctionReturn(PETSC_SUCCESS);
11143 }
11144 
11145 /*@
11146   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11147   meaning the same memory is used for the matrix, and no new memory is allocated.
11148 
11149   Collective
11150 
11151   Input Parameter:
11152 . A - the matrix
11153 
11154   Output Parameter:
11155 . A - the matrix
11156 
11157   Level: intermediate
11158 
11159 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11160 @*/
11161 PetscErrorCode MatEliminateZeros(Mat A)
11162 {
11163   PetscFunctionBegin;
11164   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11165   PetscUseTypeMethod(A, eliminatezeros);
11166   PetscFunctionReturn(PETSC_SUCCESS);
11167 }
11168