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