xref: /petsc/src/mat/interface/matrix.c (revision 2acb67f1683595f1f6a28673b20e092fb7e60070)
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_CUDACopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52    MatSetRandom - Sets all components of a matrix to random numbers.
53 
54    Logically Collective
55 
56    Input Parameters:
57 +  x  - the matrix
58 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61    Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70    Notes:
71    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
72 
73    for sparse matrices that already have locations it fills the locations with random numbers.
74 
75    It generates an error if used on sparse matrices that have not been preallocated.
76 
77 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109 
110    Logically Collective
111 
112    Input Parameter:
113 .  mat - the factored matrix
114 
115    Output Parameters:
116 +  pivot - the pivot value computed
117 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
118          the share the matrix
119 
120    Level: advanced
121 
122    Notes:
123     This routine does not work for factorizations done with external packages.
124 
125     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126 
127     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
128 
129 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
130           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscValidRealPointer(pivot, 2);
137   PetscValidIntPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144    MatFactorGetError - gets the error code from a factorization
145 
146    Logically Collective
147 
148    Input Parameter:
149 .  mat - the factored matrix
150 
151    Output Parameter:
152 .  err  - the error code
153 
154    Level: advanced
155 
156    Note:
157     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscValidPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172    MatFactorClearError - clears the error code in a factorization
173 
174    Logically Collective
175 
176    Input Parameter:
177 .  mat - the factored matrix
178 
179    Level: developer
180 
181    Note:
182     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 .    A  - the matrix
257 
258   Output Parameter:
259 .    keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264     `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscValidPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282       MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 .    A  - the matrix
286 
287   Output Parameter:
288 .    zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293     `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscValidPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323    Not Collective
324 
325    Input Parameter:
326 .   A - the matrix
327 
328    Output Parameter:
329 .   a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331    Level: advanced
332 
333    Notes:
334    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscValidPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361    Collective
362 
363    Input Parameter:
364 .  mat - the matrix
365 
366    Output Parameter:
367 .   trace - the sum of the diagonal entries
368 
369    Level: advanced
370 
371 .seealso: [](chapter_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscValidScalarPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388    MatRealPart - Zeros out the imaginary part of the matrix
389 
390    Logically Collective
391 
392    Input Parameter:
393 .  mat - the matrix
394 
395    Level: advanced
396 
397 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414    Collective
415 
416    Input Parameter:
417 .  mat - the matrix
418 
419    Output Parameters:
420 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
421 -   ghosts - the global indices of the ghost points
422 
423    Level: advanced
424 
425    Note:
426    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
427 
428 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448    Logically Collective
449 
450    Input Parameter:
451 .  mat - the matrix
452 
453    Level: advanced
454 
455 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
471 
472    Not Collective
473 
474    Input Parameter:
475 .  mat - the matrix
476 
477    Output Parameters:
478 +  missing - is any diagonal missing
479 -  dd - first diagonal entry that is missing (optional) on this process
480 
481    Level: advanced
482 
483 .seealso: [](chapter_matrices), `Mat`
484 @*/
485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
489   PetscValidType(mat, 1);
490   PetscValidBoolPointer(missing, 2);
491   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
492   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
493   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
494   PetscFunctionReturn(PETSC_SUCCESS);
495 }
496 
497 /*@C
498    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
499    for each row that you get to ensure that your application does
500    not bleed memory.
501 
502    Not Collective
503 
504    Input Parameters:
505 +  mat - the matrix
506 -  row - the row to get
507 
508    Output Parameters:
509 +  ncols -  if not `NULL`, the number of nonzeros in the row
510 .  cols - if not `NULL`, the column numbers
511 -  vals - if not `NULL`, the values
512 
513    Level: advanced
514 
515    Notes:
516    This routine is provided for people who need to have direct access
517    to the structure of a matrix.  We hope that we provide enough
518    high-level matrix routines that few users will need it.
519 
520    `MatGetRow()` always returns 0-based column indices, regardless of
521    whether the internal representation is 0-based (default) or 1-based.
522 
523    For better efficiency, set cols and/or vals to `NULL` if you do
524    not wish to extract these quantities.
525 
526    The user can only examine the values extracted with `MatGetRow()`;
527    the values cannot be altered.  To change the matrix entries, one
528    must use `MatSetValues()`.
529 
530    You can only have one call to `MatGetRow()` outstanding for a particular
531    matrix at a time, per processor. `MatGetRow()` can only obtain rows
532    associated with the given processor, it cannot get rows from the
533    other processors; for that we suggest using `MatCreateSubMatrices()`, then
534    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
535    is in the global number of rows.
536 
537    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
538 
539    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
540 
541    Fortran Note:
542    The calling sequence is
543 .vb
544    MatGetRow(matrix,row,ncols,cols,values,ierr)
545          Mat     matrix (input)
546          integer row    (input)
547          integer ncols  (output)
548          integer cols(maxcols) (output)
549          double precision (or double complex) values(maxcols) output
550 .ve
551    where maxcols >= maximum nonzeros in any row of the matrix.
552 
553    Caution:
554    Do not try to change the contents of the output arrays (`cols` and `vals`).
555    In some cases, this may corrupt the matrix.
556 
557 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   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);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578    MatConjugate - replaces the matrix values with their complex conjugates
579 
580    Logically Collective
581 
582    Input Parameter:
583 .  mat - the matrix
584 
585    Level: advanced
586 
587 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604    Not Collective
605 
606    Input Parameters:
607 +  mat - the matrix
608 .  row - the row to get
609 .  ncols - the number of nonzeros
610 .  cols - the columns of the nonzeros
611 -  vals - if nonzero the column values
612 
613    Level: advanced
614 
615    Notes:
616    This routine should be called after you have finished examining the entries.
617 
618    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
619    us of the array after it has been restored. If you pass `NULL`, it will
620    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
621 
622    Fortran Notes:
623    The calling sequence is
624 .vb
625    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
626       Mat     matrix (input)
627       integer row    (input)
628       integer ncols  (output)
629       integer cols(maxcols) (output)
630       double precision (or double complex) values(maxcols) output
631 .ve
632    Where maxcols >= maximum nonzeros in any row of the matrix.
633 
634    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
635    before another call to `MatGetRow()` can be made.
636 
637 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
638 @*/
639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
640 {
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
643   if (ncols) PetscValidIntPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657    Not Collective
658 
659    Input Parameter:
660 .  mat - the matrix
661 
662    Level: advanced
663 
664    Note:
665    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.
666 
667 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685    Not Collective
686 
687    Input Parameter:
688 .  mat - the matrix
689 
690    Level: advanced
691 
692    Note:
693    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711    MatSetOptionsPrefix - Sets the prefix used for searching for all
712    `Mat` options in the database.
713 
714    Logically Collective
715 
716    Input Parameters:
717 +  A - the matrix
718 -  prefix - the prefix to prepend to all option names
719 
720    Level: advanced
721 
722    Notes:
723    A hyphen (-) must NOT be given at the beginning of the prefix name.
724    The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726    This is NOT used for options for the factorization of the matrix. Normally the
727    prefix is automatically passed in from the PC calling the factorization. To set
728    it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742    for matrices created with `MatGetFactor()`
743 
744    Logically Collective
745 
746    Input Parameters:
747 +  A - the matrix
748 -  prefix - the prefix to prepend to all option names for the factored matrix
749 
750    Level: developer
751 
752    Notes:
753    A hyphen (-) must NOT be given at the beginning of the prefix name.
754    The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscValidCharPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778    for matrices created with `MatGetFactor()`
779 
780    Logically Collective
781 
782    Input Parameters:
783 +  A - the matrix
784 -  prefix - the prefix to prepend to all option names for the factored matrix
785 
786    Level: developer
787 
788    Notes:
789    A hyphen (-) must NOT be given at the beginning of the prefix name.
790    The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822    matrix options in the database.
823 
824    Logically Collective
825 
826    Input Parameters:
827 +  A - the matrix
828 -  prefix - the prefix to prepend to all option names
829 
830    Level: advanced
831 
832    Note:
833    A hyphen (-) must NOT be given at the beginning of the prefix name.
834    The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847    MatGetOptionsPrefix - Gets the prefix used for searching for all
848    matrix options in the database.
849 
850    Not Collective
851 
852    Input Parameter:
853 .  A - the matrix
854 
855    Output Parameter:
856 .  prefix - pointer to the prefix string used
857 
858    Level: advanced
859 
860    Fortran Note:
861    The user should pass in a string `prefix` of
862    sufficient length to hold the prefix.
863 
864 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
865 @*/
866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscValidPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
877 
878    Collective
879 
880    Input Parameter:
881 .  A - the matrix
882 
883    Level: beginner
884 
885    Notes:
886    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888    Users can reset the preallocation to access the original memory.
889 
890    Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
893 @*/
894 PetscErrorCode MatResetPreallocation(Mat A)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscValidType(A, 1);
899   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
900   PetscFunctionReturn(PETSC_SUCCESS);
901 }
902 
903 /*@
904    MatSetUp - Sets up the internal matrix data structures for later use.
905 
906    Collective
907 
908    Input Parameter:
909 .  A - the matrix
910 
911    Level: intermediate
912 
913    Notes:
914    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
915    setting values in the matrix.
916 
917    If a suitable preallocation routine is used, this function does not need to be called.
918 
919    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatSetUp(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   if (!((PetscObject)A)->type_name) {
928     PetscMPIInt size;
929 
930     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
931     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
932   }
933   if (!A->preallocated) PetscTryTypeMethod(A, setup);
934   PetscCall(PetscLayoutSetUp(A->rmap));
935   PetscCall(PetscLayoutSetUp(A->cmap));
936   A->preallocated = PETSC_TRUE;
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 #if defined(PETSC_HAVE_SAWS)
941   #include <petscviewersaws.h>
942 #endif
943 
944 /*@C
945    MatViewFromOptions - View properties of the matrix based on options set in the options database
946 
947    Collective
948 
949    Input Parameters:
950 +  A - the matrix
951 .  obj - optional additional object that provides the options prefix to use
952 -  name - command line option
953 
954   Options Database Key:
955 .  -mat_view [viewertype]:... - the viewer and its options
956 
957    Level: intermediate
958 
959   Notes:
960 .vb
961     If no value is provided ascii:stdout is used
962        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
963                                                   for example ascii::ascii_info prints just the information about the object not all details
964                                                   unless :append is given filename opens in write mode, overwriting what was already there
965        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
966        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
967        socket[:port]                             defaults to the standard output port
968        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
969 .ve
970 
971 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
972 @*/
973 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
974 {
975   PetscFunctionBegin;
976   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
977   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
978   PetscFunctionReturn(PETSC_SUCCESS);
979 }
980 
981 /*@C
982    MatView - display information about a matrix in a variety ways
983 
984    Collective
985 
986    Input Parameters:
987 +  mat - the matrix
988 -  viewer - visualization context
989 
990    Options Database Keys:
991 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
992 .  -mat_view ::ascii_info_detail - Prints more detailed info
993 .  -mat_view - Prints matrix in ASCII format
994 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
995 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
996 .  -display <name> - Sets display name (default is host)
997 .  -draw_pause <sec> - Sets number of seconds to pause after display
998 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
999 .  -viewer_socket_machine <machine> -
1000 .  -viewer_socket_port <port> -
1001 .  -mat_view binary - save matrix to file in binary format
1002 -  -viewer_binary_filename <name> -
1003 
1004    Level: beginner
1005 
1006   Notes:
1007   The available visualization contexts include
1008 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1009 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1010 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1011 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1012 
1013    The user can open alternative visualization contexts with
1014 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1015 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1016          specified file; corresponding input uses MatLoad()
1017 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1018          an X window display
1019 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1020          Currently only the sequential dense and AIJ
1021          matrix types support the Socket viewer.
1022 
1023    The user can call `PetscViewerPushFormat()` to specify the output
1024    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1025    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1026 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1027 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1028 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1029 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1030          format common among all matrix types
1031 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1032          format (which is in many cases the same as the default)
1033 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1034          size and structure (not the matrix entries)
1035 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1036          the matrix structure
1037 
1038     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1039     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1040 
1041     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1042 
1043     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1044       viewer is used.
1045 
1046       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1047       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1048 
1049       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1050       and then use the following mouse functions.
1051 .vb
1052   left mouse: zoom in
1053   middle mouse: zoom out
1054   right mouse: continue with the simulation
1055 .ve
1056 
1057 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1058           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1059 @*/
1060 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1061 {
1062   PetscInt          rows, cols, rbs, cbs;
1063   PetscBool         isascii, isstring, issaws;
1064   PetscViewerFormat format;
1065   PetscMPIInt       size;
1066 
1067   PetscFunctionBegin;
1068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1069   PetscValidType(mat, 1);
1070   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1071   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1072   PetscCheckSameComm(mat, 1, viewer, 2);
1073 
1074   PetscCall(PetscViewerGetFormat(viewer, &format));
1075   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1076   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1077 
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1080   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1081   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");
1082 
1083   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1084   if (isascii) {
1085     if (!mat->preallocated) {
1086       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1087       PetscFunctionReturn(PETSC_SUCCESS);
1088     }
1089     if (!mat->assembled) {
1090       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1091       PetscFunctionReturn(PETSC_SUCCESS);
1092     }
1093     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1094     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1095       MatNullSpace nullsp, transnullsp;
1096 
1097       PetscCall(PetscViewerASCIIPushTab(viewer));
1098       PetscCall(MatGetSize(mat, &rows, &cols));
1099       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1100       if (rbs != 1 || cbs != 1) {
1101         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1102         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1103       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1104       if (mat->factortype) {
1105         MatSolverType solver;
1106         PetscCall(MatFactorGetSolverType(mat, &solver));
1107         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1108       }
1109       if (mat->ops->getinfo) {
1110         MatInfo info;
1111         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1112         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1113         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1114       }
1115       PetscCall(MatGetNullSpace(mat, &nullsp));
1116       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1117       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1118       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1119       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1120       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1121       PetscCall(PetscViewerASCIIPushTab(viewer));
1122       PetscCall(MatProductView(mat, viewer));
1123       PetscCall(PetscViewerASCIIPopTab(viewer));
1124     }
1125   } else if (issaws) {
1126 #if defined(PETSC_HAVE_SAWS)
1127     PetscMPIInt rank;
1128 
1129     PetscCall(PetscObjectName((PetscObject)mat));
1130     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1131     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1132 #endif
1133   } else if (isstring) {
1134     const char *type;
1135     PetscCall(MatGetType(mat, &type));
1136     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1137     PetscTryTypeMethod(mat, view, viewer);
1138   }
1139   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1140     PetscCall(PetscViewerASCIIPushTab(viewer));
1141     PetscUseTypeMethod(mat, viewnative, viewer);
1142     PetscCall(PetscViewerASCIIPopTab(viewer));
1143   } else if (mat->ops->view) {
1144     PetscCall(PetscViewerASCIIPushTab(viewer));
1145     PetscUseTypeMethod(mat, view, viewer);
1146     PetscCall(PetscViewerASCIIPopTab(viewer));
1147   }
1148   if (isascii) {
1149     PetscCall(PetscViewerGetFormat(viewer, &format));
1150     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1151   }
1152   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1153   PetscFunctionReturn(PETSC_SUCCESS);
1154 }
1155 
1156 #if defined(PETSC_USE_DEBUG)
1157   #include <../src/sys/totalview/tv_data_display.h>
1158 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1159 {
1160   TV_add_row("Local rows", "int", &mat->rmap->n);
1161   TV_add_row("Local columns", "int", &mat->cmap->n);
1162   TV_add_row("Global rows", "int", &mat->rmap->N);
1163   TV_add_row("Global columns", "int", &mat->cmap->N);
1164   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1165   return TV_format_OK;
1166 }
1167 #endif
1168 
1169 /*@C
1170    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1171    with `MatView()`.  The matrix format is determined from the options database.
1172    Generates a parallel MPI matrix if the communicator has more than one
1173    processor.  The default matrix type is `MATAIJ`.
1174 
1175    Collective
1176 
1177    Input Parameters:
1178 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1179             or some related function before a call to `MatLoad()`
1180 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1181 
1182    Options Database Keys:
1183    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1184    block size
1185 .    -matload_block_size <bs> - set block size
1186 
1187    Level: beginner
1188 
1189    Notes:
1190    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1191    `Mat` before calling this routine if you wish to set it from the options database.
1192 
1193    `MatLoad()` automatically loads into the options database any options
1194    given in the file filename.info where filename is the name of the file
1195    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1196    file will be ignored if you use the -viewer_binary_skip_info option.
1197 
1198    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1199    sets the default matrix type AIJ and sets the local and global sizes.
1200    If type and/or size is already set, then the same are used.
1201 
1202    In parallel, each processor can load a subset of rows (or the
1203    entire matrix).  This routine is especially useful when a large
1204    matrix is stored on disk and only part of it is desired on each
1205    processor.  For example, a parallel solver may access only some of
1206    the rows from each processor.  The algorithm used here reads
1207    relatively small blocks of data rather than reading the entire
1208    matrix and then subsetting it.
1209 
1210    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1211    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1212    or the sequence like
1213 .vb
1214     `PetscViewer` v;
1215     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1216     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1217     `PetscViewerSetFromOptions`(v);
1218     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1219     `PetscViewerFileSetName`(v,"datafile");
1220 .ve
1221    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1222 $ -viewer_type {binary,hdf5}
1223 
1224    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1225    and src/mat/tutorials/ex10.c with the second approach.
1226 
1227    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1228    is read onto rank 0 and then shipped to its destination rank, one after another.
1229    Multiple objects, both matrices and vectors, can be stored within the same file.
1230    Their PetscObject name is ignored; they are loaded in the order of their storage.
1231 
1232    Most users should not need to know the details of the binary storage
1233    format, since `MatLoad()` and `MatView()` completely hide these details.
1234    But for anyone who's interested, the standard binary matrix storage
1235    format is
1236 
1237 .vb
1238     PetscInt    MAT_FILE_CLASSID
1239     PetscInt    number of rows
1240     PetscInt    number of columns
1241     PetscInt    total number of nonzeros
1242     PetscInt    *number nonzeros in each row
1243     PetscInt    *column indices of all nonzeros (starting index is zero)
1244     PetscScalar *values of all nonzeros
1245 .ve
1246 
1247    PETSc automatically does the byte swapping for
1248 machines that store the bytes reversed. Thus if you write your own binary
1249 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1250 and `PetscBinaryWrite()` to see how this may be done.
1251 
1252    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1253    Each processor's chunk is loaded independently by its owning rank.
1254    Multiple objects, both matrices and vectors, can be stored within the same file.
1255    They are looked up by their PetscObject name.
1256 
1257    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1258    by default the same structure and naming of the AIJ arrays and column count
1259    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1260 $    save example.mat A b -v7.3
1261    can be directly read by this routine (see Reference 1 for details).
1262 
1263    Depending on your MATLAB version, this format might be a default,
1264    otherwise you can set it as default in Preferences.
1265 
1266    Unless -nocompression flag is used to save the file in MATLAB,
1267    PETSc must be configured with ZLIB package.
1268 
1269    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1270 
1271    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1272 
1273    Corresponding `MatView()` is not yet implemented.
1274 
1275    The loaded matrix is actually a transpose of the original one in MATLAB,
1276    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1277    With this format, matrix is automatically transposed by PETSc,
1278    unless the matrix is marked as SPD or symmetric
1279    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1280 
1281    References:
1282 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1283 
1284 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1285  @*/
1286 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1287 {
1288   PetscBool flg;
1289 
1290   PetscFunctionBegin;
1291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1292   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1293 
1294   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1295 
1296   flg = PETSC_FALSE;
1297   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1298   if (flg) {
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1300     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1301   }
1302   flg = PETSC_FALSE;
1303   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1304   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1305 
1306   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1307   PetscUseTypeMethod(mat, load, viewer);
1308   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1309   PetscFunctionReturn(PETSC_SUCCESS);
1310 }
1311 
1312 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1313 {
1314   Mat_Redundant *redund = *redundant;
1315 
1316   PetscFunctionBegin;
1317   if (redund) {
1318     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1319       PetscCall(ISDestroy(&redund->isrow));
1320       PetscCall(ISDestroy(&redund->iscol));
1321       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1322     } else {
1323       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1324       PetscCall(PetscFree(redund->sbuf_j));
1325       PetscCall(PetscFree(redund->sbuf_a));
1326       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1327         PetscCall(PetscFree(redund->rbuf_j[i]));
1328         PetscCall(PetscFree(redund->rbuf_a[i]));
1329       }
1330       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1331     }
1332 
1333     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1334     PetscCall(PetscFree(redund));
1335   }
1336   PetscFunctionReturn(PETSC_SUCCESS);
1337 }
1338 
1339 /*@C
1340    MatDestroy - Frees space taken by a matrix.
1341 
1342    Collective
1343 
1344    Input Parameter:
1345 .  A - the matrix
1346 
1347    Level: beginner
1348 
1349    Developer Note:
1350    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1351    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1352    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1353    if changes are needed here.
1354 
1355 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1356 @*/
1357 PetscErrorCode MatDestroy(Mat *A)
1358 {
1359   PetscFunctionBegin;
1360   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1361   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1362   if (--((PetscObject)(*A))->refct > 0) {
1363     *A = NULL;
1364     PetscFunctionReturn(PETSC_SUCCESS);
1365   }
1366 
1367   /* if memory was published with SAWs then destroy it */
1368   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1369   PetscTryTypeMethod((*A), destroy);
1370 
1371   PetscCall(PetscFree((*A)->factorprefix));
1372   PetscCall(PetscFree((*A)->defaultvectype));
1373   PetscCall(PetscFree((*A)->defaultrandtype));
1374   PetscCall(PetscFree((*A)->bsizes));
1375   PetscCall(PetscFree((*A)->solvertype));
1376   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1377   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1378   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1379   PetscCall(MatProductClear(*A));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1382   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1383   PetscCall(MatDestroy(&(*A)->schur));
1384   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1385   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1386   PetscCall(PetscHeaderDestroy(A));
1387   PetscFunctionReturn(PETSC_SUCCESS);
1388 }
1389 
1390 /*@C
1391    MatSetValues - Inserts or adds a block of values into a matrix.
1392    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1393    MUST be called after all calls to `MatSetValues()` have been completed.
1394 
1395    Not Collective
1396 
1397    Input Parameters:
1398 +  mat - the matrix
1399 .  v - a logically two-dimensional array of values
1400 .  m - the number of rows
1401 .  idxm - the global indices of the rows
1402 .  n - the number of columns
1403 .  idxn - the global indices of the columns
1404 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1405 
1406    Level: beginner
1407 
1408    Notes:
1409    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1410 
1411    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1412    options cannot be mixed without intervening calls to the assembly
1413    routines.
1414 
1415    `MatSetValues()` uses 0-based row and column numbers in Fortran
1416    as well as in C.
1417 
1418    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1419    simply ignored. This allows easily inserting element stiffness matrices
1420    with homogeneous Dirchlet boundary conditions that you don't want represented
1421    in the matrix.
1422 
1423    Efficiency Alert:
1424    The routine `MatSetValuesBlocked()` may offer much better efficiency
1425    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1426 
1427    Developer Note:
1428    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1429    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1430 
1431 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1432           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1433 @*/
1434 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1435 {
1436   PetscFunctionBeginHot;
1437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1438   PetscValidType(mat, 1);
1439   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1440   PetscValidIntPointer(idxm, 3);
1441   PetscValidIntPointer(idxn, 5);
1442   MatCheckPreallocated(mat, 1);
1443 
1444   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1445   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1446 
1447   if (PetscDefined(USE_DEBUG)) {
1448     PetscInt i, j;
1449 
1450     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1451     for (i = 0; i < m; i++) {
1452       for (j = 0; j < n; j++) {
1453         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1454 #if defined(PETSC_USE_COMPLEX)
1455           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]);
1456 #else
1457           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]);
1458 #endif
1459       }
1460     }
1461     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);
1462     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);
1463   }
1464 
1465   if (mat->assembled) {
1466     mat->was_assembled = PETSC_TRUE;
1467     mat->assembled     = PETSC_FALSE;
1468   }
1469   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1470   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1471   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1472   PetscFunctionReturn(PETSC_SUCCESS);
1473 }
1474 
1475 /*@C
1476    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1477    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1478    MUST be called after all calls to `MatSetValues()` have been completed.
1479 
1480    Not Collective
1481 
1482    Input Parameters:
1483 +  mat - the matrix
1484 .  v - a logically two-dimensional array of values
1485 .  ism - the rows to provide
1486 .  isn - the columns to provide
1487 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1488 
1489    Level: beginner
1490 
1491    Notes:
1492    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1493 
1494    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1495    options cannot be mixed without intervening calls to the assembly
1496    routines.
1497 
1498    `MatSetValues()` uses 0-based row and column numbers in Fortran
1499    as well as in C.
1500 
1501    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1502    simply ignored. This allows easily inserting element stiffness matrices
1503    with homogeneous Dirchlet boundary conditions that you don't want represented
1504    in the matrix.
1505 
1506    Efficiency Alert:
1507    The routine `MatSetValuesBlocked()` may offer much better efficiency
1508    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1509 
1510     This is currently not optimized for any particular `ISType`
1511 
1512    Developer Notes:
1513     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1514                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1515 
1516 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1517           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1518 @*/
1519 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1520 {
1521   PetscInt        m, n;
1522   const PetscInt *rows, *cols;
1523 
1524   PetscFunctionBeginHot;
1525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1526   PetscCall(ISGetIndices(ism, &rows));
1527   PetscCall(ISGetIndices(isn, &cols));
1528   PetscCall(ISGetLocalSize(ism, &m));
1529   PetscCall(ISGetLocalSize(isn, &n));
1530   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1531   PetscCall(ISRestoreIndices(ism, &rows));
1532   PetscCall(ISRestoreIndices(isn, &cols));
1533   PetscFunctionReturn(PETSC_SUCCESS);
1534 }
1535 
1536 /*@
1537    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1538         values into a matrix
1539 
1540    Not Collective
1541 
1542    Input Parameters:
1543 +  mat - the matrix
1544 .  row - the (block) row to set
1545 -  v - a logically two-dimensional array of values
1546 
1547    Level: intermediate
1548 
1549    Notes:
1550    The values, `v`, are column-oriented (for the block version) and sorted
1551 
1552    All the nonzeros in the row must be provided
1553 
1554    The matrix must have previously had its column indices set, likely by having been assembled.
1555 
1556    The row must belong to this process
1557 
1558 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1559           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1560 @*/
1561 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1562 {
1563   PetscInt globalrow;
1564 
1565   PetscFunctionBegin;
1566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1567   PetscValidType(mat, 1);
1568   PetscValidScalarPointer(v, 3);
1569   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1570   PetscCall(MatSetValuesRow(mat, globalrow, v));
1571   PetscFunctionReturn(PETSC_SUCCESS);
1572 }
1573 
1574 /*@
1575    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1576         values into a matrix
1577 
1578    Not Collective
1579 
1580    Input Parameters:
1581 +  mat - the matrix
1582 .  row - the (block) row to set
1583 -  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
1584 
1585    Level: advanced
1586 
1587    Notes:
1588    The values, `v`, are column-oriented for the block version.
1589 
1590    All the nonzeros in the row must be provided
1591 
1592    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1593 
1594    The row must belong to this process
1595 
1596 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1597           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1598 @*/
1599 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1600 {
1601   PetscFunctionBeginHot;
1602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1603   PetscValidType(mat, 1);
1604   MatCheckPreallocated(mat, 1);
1605   PetscValidScalarPointer(v, 3);
1606   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1607   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1608   mat->insertmode = INSERT_VALUES;
1609 
1610   if (mat->assembled) {
1611     mat->was_assembled = PETSC_TRUE;
1612     mat->assembled     = PETSC_FALSE;
1613   }
1614   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1615   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1616   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1617   PetscFunctionReturn(PETSC_SUCCESS);
1618 }
1619 
1620 /*@
1621    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1622      Using structured grid indexing
1623 
1624    Not Collective
1625 
1626    Input Parameters:
1627 +  mat - the matrix
1628 .  m - number of rows being entered
1629 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1630 .  n - number of columns being entered
1631 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1632 .  v - a logically two-dimensional array of values
1633 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1634 
1635    Level: beginner
1636 
1637    Notes:
1638    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1639 
1640    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1641    options cannot be mixed without intervening calls to the assembly
1642    routines.
1643 
1644    The grid coordinates are across the entire grid, not just the local portion
1645 
1646    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1647    as well as in C.
1648 
1649    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1650 
1651    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1652    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1653 
1654    The columns and rows in the stencil passed in MUST be contained within the
1655    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1656    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1657    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1658    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1659 
1660    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1661    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1662    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1663    `DM_BOUNDARY_PERIODIC` boundary type.
1664 
1665    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
1666    a single value per point) you can skip filling those indices.
1667 
1668    Inspired by the structured grid interface to the HYPRE package
1669    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1670 
1671    Efficiency Alert:
1672    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1673    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1674 
1675    Fortran Note:
1676    `idxm` and `idxn` should be declared as
1677 $     MatStencil idxm(4,m),idxn(4,n)
1678    and the values inserted using
1679 .vb
1680     idxm(MatStencil_i,1) = i
1681     idxm(MatStencil_j,1) = j
1682     idxm(MatStencil_k,1) = k
1683     idxm(MatStencil_c,1) = c
1684     etc
1685 .ve
1686 
1687 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1688           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1689 @*/
1690 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1691 {
1692   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1693   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1694   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1695 
1696   PetscFunctionBegin;
1697   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1699   PetscValidType(mat, 1);
1700   PetscValidPointer(idxm, 3);
1701   PetscValidPointer(idxn, 5);
1702 
1703   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1704     jdxm = buf;
1705     jdxn = buf + m;
1706   } else {
1707     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1708     jdxm = bufm;
1709     jdxn = bufn;
1710   }
1711   for (i = 0; i < m; i++) {
1712     for (j = 0; j < 3 - sdim; j++) dxm++;
1713     tmp = *dxm++ - starts[0];
1714     for (j = 0; j < dim - 1; j++) {
1715       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1716       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1717     }
1718     if (mat->stencil.noc) dxm++;
1719     jdxm[i] = tmp;
1720   }
1721   for (i = 0; i < n; i++) {
1722     for (j = 0; j < 3 - sdim; j++) dxn++;
1723     tmp = *dxn++ - starts[0];
1724     for (j = 0; j < dim - 1; j++) {
1725       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1726       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1727     }
1728     if (mat->stencil.noc) dxn++;
1729     jdxn[i] = tmp;
1730   }
1731   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1732   PetscCall(PetscFree2(bufm, bufn));
1733   PetscFunctionReturn(PETSC_SUCCESS);
1734 }
1735 
1736 /*@
1737    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1738      Using structured grid indexing
1739 
1740    Not Collective
1741 
1742    Input Parameters:
1743 +  mat - the matrix
1744 .  m - number of rows being entered
1745 .  idxm - grid coordinates for matrix rows being entered
1746 .  n - number of columns being entered
1747 .  idxn - grid coordinates for matrix columns being entered
1748 .  v - a logically two-dimensional array of values
1749 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1750 
1751    Level: beginner
1752 
1753    Notes:
1754    By default the values, `v`, are row-oriented and unsorted.
1755    See `MatSetOption()` for other options.
1756 
1757    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1758    options cannot be mixed without intervening calls to the assembly
1759    routines.
1760 
1761    The grid coordinates are across the entire grid, not just the local portion
1762 
1763    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1764    as well as in C.
1765 
1766    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1767 
1768    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1769    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1770 
1771    The columns and rows in the stencil passed in MUST be contained within the
1772    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1773    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1774    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1775    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1776 
1777    Negative indices may be passed in idxm and idxn, these rows and columns are
1778    simply ignored. This allows easily inserting element stiffness matrices
1779    with homogeneous Dirchlet boundary conditions that you don't want represented
1780    in the matrix.
1781 
1782    Inspired by the structured grid interface to the HYPRE package
1783    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1784 
1785    Fortran Note:
1786    `idxm` and `idxn` should be declared as
1787 $     MatStencil idxm(4,m),idxn(4,n)
1788    and the values inserted using
1789 .vb
1790     idxm(MatStencil_i,1) = i
1791     idxm(MatStencil_j,1) = j
1792     idxm(MatStencil_k,1) = k
1793    etc
1794 .ve
1795 
1796 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1798           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1799 @*/
1800 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1801 {
1802   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1803   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1804   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1805 
1806   PetscFunctionBegin;
1807   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1809   PetscValidType(mat, 1);
1810   PetscValidPointer(idxm, 3);
1811   PetscValidPointer(idxn, 5);
1812   PetscValidScalarPointer(v, 6);
1813 
1814   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1815     jdxm = buf;
1816     jdxn = buf + m;
1817   } else {
1818     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1819     jdxm = bufm;
1820     jdxn = bufn;
1821   }
1822   for (i = 0; i < m; i++) {
1823     for (j = 0; j < 3 - sdim; j++) dxm++;
1824     tmp = *dxm++ - starts[0];
1825     for (j = 0; j < sdim - 1; j++) {
1826       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1827       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1828     }
1829     dxm++;
1830     jdxm[i] = tmp;
1831   }
1832   for (i = 0; i < n; i++) {
1833     for (j = 0; j < 3 - sdim; j++) dxn++;
1834     tmp = *dxn++ - starts[0];
1835     for (j = 0; j < sdim - 1; j++) {
1836       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1837       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1838     }
1839     dxn++;
1840     jdxn[i] = tmp;
1841   }
1842   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1843   PetscCall(PetscFree2(bufm, bufn));
1844   PetscFunctionReturn(PETSC_SUCCESS);
1845 }
1846 
1847 /*@
1848    MatSetStencil - Sets the grid information for setting values into a matrix via
1849         `MatSetValuesStencil()`
1850 
1851    Not Collective
1852 
1853    Input Parameters:
1854 +  mat - the matrix
1855 .  dim - dimension of the grid 1, 2, or 3
1856 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1857 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1858 -  dof - number of degrees of freedom per node
1859 
1860    Level: beginner
1861 
1862    Notes:
1863    Inspired by the structured grid interface to the HYPRE package
1864    (www.llnl.gov/CASC/hyper)
1865 
1866    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1867    user.
1868 
1869 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1870           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1871 @*/
1872 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1873 {
1874   PetscFunctionBegin;
1875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1876   PetscValidIntPointer(dims, 3);
1877   PetscValidIntPointer(starts, 4);
1878 
1879   mat->stencil.dim = dim + (dof > 1);
1880   for (PetscInt i = 0; i < dim; i++) {
1881     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1882     mat->stencil.starts[i] = starts[dim - i - 1];
1883   }
1884   mat->stencil.dims[dim]   = dof;
1885   mat->stencil.starts[dim] = 0;
1886   mat->stencil.noc         = (PetscBool)(dof == 1);
1887   PetscFunctionReturn(PETSC_SUCCESS);
1888 }
1889 
1890 /*@C
1891    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1892 
1893    Not Collective
1894 
1895    Input Parameters:
1896 +  mat - the matrix
1897 .  v - a logically two-dimensional array of values
1898 .  m  - the number of block rows
1899 .  idxm - the global block indices
1900 .  n - the number of block columns
1901 .  idxn - the global block indices
1902 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1903 
1904    Level: intermediate
1905 
1906    Notes:
1907    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1908    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1909 
1910    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1911    NOT the total number of rows/columns; for example, if the block size is 2 and
1912    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1913    The values in idxm would be 1 2; that is the first index for each block divided by
1914    the block size.
1915 
1916    You must call `MatSetBlockSize()` when constructing this matrix (before
1917    preallocating it).
1918 
1919    By default the values, `v`, are row-oriented, so the layout of
1920    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1921 
1922    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1923    options cannot be mixed without intervening calls to the assembly
1924    routines.
1925 
1926    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1927    as well as in C.
1928 
1929    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1930    simply ignored. This allows easily inserting element stiffness matrices
1931    with homogeneous Dirchlet boundary conditions that you don't want represented
1932    in the matrix.
1933 
1934    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1935    internal searching must be done to determine where to place the
1936    data in the matrix storage space.  By instead inserting blocks of
1937    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1938    reduced.
1939 
1940    Example:
1941 .vb
1942    Suppose m=n=2 and block size(bs) = 2 The array is
1943 
1944    1  2  | 3  4
1945    5  6  | 7  8
1946    - - - | - - -
1947    9  10 | 11 12
1948    13 14 | 15 16
1949 
1950    v[] should be passed in like
1951    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1952 
1953   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1954    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1955 .ve
1956 
1957 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1958 @*/
1959 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1960 {
1961   PetscFunctionBeginHot;
1962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1963   PetscValidType(mat, 1);
1964   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1965   PetscValidIntPointer(idxm, 3);
1966   PetscValidIntPointer(idxn, 5);
1967   MatCheckPreallocated(mat, 1);
1968   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1969   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1970   if (PetscDefined(USE_DEBUG)) {
1971     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1972     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1973   }
1974   if (PetscDefined(USE_DEBUG)) {
1975     PetscInt rbs, cbs, M, N, i;
1976     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1977     PetscCall(MatGetSize(mat, &M, &N));
1978     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);
1979     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);
1980   }
1981   if (mat->assembled) {
1982     mat->was_assembled = PETSC_TRUE;
1983     mat->assembled     = PETSC_FALSE;
1984   }
1985   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1986   if (mat->ops->setvaluesblocked) {
1987     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1988   } else {
1989     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1990     PetscInt i, j, bs, cbs;
1991 
1992     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1993     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1994       iidxm = buf;
1995       iidxn = buf + m * bs;
1996     } else {
1997       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1998       iidxm = bufr;
1999       iidxn = bufc;
2000     }
2001     for (i = 0; i < m; i++) {
2002       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2003     }
2004     if (m != n || bs != cbs || idxm != idxn) {
2005       for (i = 0; i < n; i++) {
2006         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2007       }
2008     } else iidxn = iidxm;
2009     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2010     PetscCall(PetscFree2(bufr, bufc));
2011   }
2012   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2013   PetscFunctionReturn(PETSC_SUCCESS);
2014 }
2015 
2016 /*@C
2017    MatGetValues - Gets a block of local values from a matrix.
2018 
2019    Not Collective; can only return values that are owned by the give process
2020 
2021    Input Parameters:
2022 +  mat - the matrix
2023 .  v - a logically two-dimensional array for storing the values
2024 .  m  - the number of rows
2025 .  idxm - the  global indices of the rows
2026 .  n - the number of columns
2027 -  idxn - the global indices of the columns
2028 
2029    Level: advanced
2030 
2031    Notes:
2032      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2033      The values, `v`, are then returned in a row-oriented format,
2034      analogous to that used by default in `MatSetValues()`.
2035 
2036      `MatGetValues()` uses 0-based row and column numbers in
2037      Fortran as well as in C.
2038 
2039      `MatGetValues()` requires that the matrix has been assembled
2040      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2041      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2042      without intermediate matrix assembly.
2043 
2044      Negative row or column indices will be ignored and those locations in `v` will be
2045      left unchanged.
2046 
2047      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2048      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2049      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2050 
2051 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2052 @*/
2053 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2054 {
2055   PetscFunctionBegin;
2056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2057   PetscValidType(mat, 1);
2058   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2059   PetscValidIntPointer(idxm, 3);
2060   PetscValidIntPointer(idxn, 5);
2061   PetscValidScalarPointer(v, 6);
2062   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2063   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2064   MatCheckPreallocated(mat, 1);
2065 
2066   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2067   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2068   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2069   PetscFunctionReturn(PETSC_SUCCESS);
2070 }
2071 
2072 /*@C
2073    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2074      defined previously by `MatSetLocalToGlobalMapping()`
2075 
2076    Not Collective
2077 
2078    Input Parameters:
2079 +  mat - the matrix
2080 .  nrow - number of rows
2081 .  irow - the row local indices
2082 .  ncol - number of columns
2083 -  icol - the column local indices
2084 
2085    Output Parameter:
2086 .  y -  a logically two-dimensional array of values
2087 
2088    Level: advanced
2089 
2090    Notes:
2091      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2092 
2093      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,
2094      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2095      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2096      with `MatSetLocalToGlobalMapping()`.
2097 
2098    Developer Note:
2099       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2100       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2101 
2102 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2103           `MatSetValuesLocal()`, `MatGetValues()`
2104 @*/
2105 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2106 {
2107   PetscFunctionBeginHot;
2108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2109   PetscValidType(mat, 1);
2110   MatCheckPreallocated(mat, 1);
2111   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2112   PetscValidIntPointer(irow, 3);
2113   PetscValidIntPointer(icol, 5);
2114   if (PetscDefined(USE_DEBUG)) {
2115     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2116     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2117   }
2118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2119   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2120   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2121   else {
2122     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2123     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2124       irowm = buf;
2125       icolm = buf + nrow;
2126     } else {
2127       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2128       irowm = bufr;
2129       icolm = bufc;
2130     }
2131     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2133     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2134     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2135     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2136     PetscCall(PetscFree2(bufr, bufc));
2137   }
2138   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2139   PetscFunctionReturn(PETSC_SUCCESS);
2140 }
2141 
2142 /*@
2143   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2144   the same size. Currently, this can only be called once and creates the given matrix.
2145 
2146   Not Collective
2147 
2148   Input Parameters:
2149 + mat - the matrix
2150 . nb - the number of blocks
2151 . bs - the number of rows (and columns) in each block
2152 . rows - a concatenation of the rows for each block
2153 - v - a concatenation of logically two-dimensional arrays of values
2154 
2155   Level: advanced
2156 
2157   Note:
2158   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2159 
2160   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2161 
2162 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2163           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2164 @*/
2165 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2166 {
2167   PetscFunctionBegin;
2168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2169   PetscValidType(mat, 1);
2170   PetscValidIntPointer(rows, 4);
2171   PetscValidScalarPointer(v, 5);
2172   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2173 
2174   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2175   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2176   else {
2177     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2178   }
2179   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@
2184    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2185    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2186    using a local (per-processor) numbering.
2187 
2188    Not Collective
2189 
2190    Input Parameters:
2191 +  x - the matrix
2192 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2193 -  cmapping - column mapping
2194 
2195    Level: intermediate
2196 
2197    Note:
2198    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2199 
2200 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2201 @*/
2202 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2203 {
2204   PetscFunctionBegin;
2205   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2206   PetscValidType(x, 1);
2207   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2208   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2209   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2210   else {
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2212     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2213   }
2214   PetscFunctionReturn(PETSC_SUCCESS);
2215 }
2216 
2217 /*@
2218    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2219 
2220    Not Collective
2221 
2222    Input Parameter:
2223 .  A - the matrix
2224 
2225    Output Parameters:
2226 + rmapping - row mapping
2227 - cmapping - column mapping
2228 
2229    Level: advanced
2230 
2231 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2232 @*/
2233 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2234 {
2235   PetscFunctionBegin;
2236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2237   PetscValidType(A, 1);
2238   if (rmapping) {
2239     PetscValidPointer(rmapping, 2);
2240     *rmapping = A->rmap->mapping;
2241   }
2242   if (cmapping) {
2243     PetscValidPointer(cmapping, 3);
2244     *cmapping = A->cmap->mapping;
2245   }
2246   PetscFunctionReturn(PETSC_SUCCESS);
2247 }
2248 
2249 /*@
2250    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2251 
2252    Logically Collective
2253 
2254    Input Parameters:
2255 +  A - the matrix
2256 . rmap - row layout
2257 - cmap - column layout
2258 
2259    Level: advanced
2260 
2261    Note:
2262    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2263 
2264 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2265 @*/
2266 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2267 {
2268   PetscFunctionBegin;
2269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2270   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2271   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2272   PetscFunctionReturn(PETSC_SUCCESS);
2273 }
2274 
2275 /*@
2276    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2277 
2278    Not Collective
2279 
2280    Input Parameter:
2281 .  A - the matrix
2282 
2283    Output Parameters:
2284 + rmap - row layout
2285 - cmap - column layout
2286 
2287    Level: advanced
2288 
2289 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2290 @*/
2291 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2292 {
2293   PetscFunctionBegin;
2294   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2295   PetscValidType(A, 1);
2296   if (rmap) {
2297     PetscValidPointer(rmap, 2);
2298     *rmap = A->rmap;
2299   }
2300   if (cmap) {
2301     PetscValidPointer(cmap, 3);
2302     *cmap = A->cmap;
2303   }
2304   PetscFunctionReturn(PETSC_SUCCESS);
2305 }
2306 
2307 /*@C
2308    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2309    using a local numbering of the nodes.
2310 
2311    Not Collective
2312 
2313    Input Parameters:
2314 +  mat - the matrix
2315 .  nrow - number of rows
2316 .  irow - the row local indices
2317 .  ncol - number of columns
2318 .  icol - the column local indices
2319 .  y -  a logically two-dimensional array of values
2320 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2321 
2322    Level: intermediate
2323 
2324    Notes:
2325    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2326       `MatSetUp()` before using this routine
2327 
2328    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2329 
2330    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2331    options cannot be mixed without intervening calls to the assembly
2332    routines.
2333 
2334    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2335    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2336 
2337    Developer Note:
2338     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2339                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2340 
2341 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2342           `MatGetValuesLocal()`
2343 @*/
2344 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2345 {
2346   PetscFunctionBeginHot;
2347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2348   PetscValidType(mat, 1);
2349   MatCheckPreallocated(mat, 1);
2350   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2351   PetscValidIntPointer(irow, 3);
2352   PetscValidIntPointer(icol, 5);
2353   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2354   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2355   if (PetscDefined(USE_DEBUG)) {
2356     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2357     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2358   }
2359 
2360   if (mat->assembled) {
2361     mat->was_assembled = PETSC_TRUE;
2362     mat->assembled     = PETSC_FALSE;
2363   }
2364   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2365   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2366   else {
2367     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2368     const PetscInt *irowm, *icolm;
2369 
2370     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2371       bufr  = buf;
2372       bufc  = buf + nrow;
2373       irowm = bufr;
2374       icolm = bufc;
2375     } else {
2376       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2377       irowm = bufr;
2378       icolm = bufc;
2379     }
2380     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2381     else irowm = irow;
2382     if (mat->cmap->mapping) {
2383       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2384         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2385       } else icolm = irowm;
2386     } else icolm = icol;
2387     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2388     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2389   }
2390   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2391   PetscFunctionReturn(PETSC_SUCCESS);
2392 }
2393 
2394 /*@C
2395    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2396    using a local ordering of the nodes a block at a time.
2397 
2398    Not Collective
2399 
2400    Input Parameters:
2401 +  x - the matrix
2402 .  nrow - number of rows
2403 .  irow - the row local indices
2404 .  ncol - number of columns
2405 .  icol - the column local indices
2406 .  y -  a logically two-dimensional array of values
2407 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2408 
2409    Level: intermediate
2410 
2411    Notes:
2412    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2413       `MatSetUp()` before using this routine
2414 
2415    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2416       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2417 
2418    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2419    options cannot be mixed without intervening calls to the assembly
2420    routines.
2421 
2422    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2423    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2424 
2425    Developer Note:
2426     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2427                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2428 
2429 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2430           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2431 @*/
2432 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2433 {
2434   PetscFunctionBeginHot;
2435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2436   PetscValidType(mat, 1);
2437   MatCheckPreallocated(mat, 1);
2438   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2439   PetscValidIntPointer(irow, 3);
2440   PetscValidIntPointer(icol, 5);
2441   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2442   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2443   if (PetscDefined(USE_DEBUG)) {
2444     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2445     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);
2446   }
2447 
2448   if (mat->assembled) {
2449     mat->was_assembled = PETSC_TRUE;
2450     mat->assembled     = PETSC_FALSE;
2451   }
2452   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2453     PetscInt irbs, rbs;
2454     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2455     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2456     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2457   }
2458   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2459     PetscInt icbs, cbs;
2460     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2461     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2462     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2463   }
2464   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2465   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2466   else {
2467     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2468     const PetscInt *irowm, *icolm;
2469 
2470     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2471       bufr  = buf;
2472       bufc  = buf + nrow;
2473       irowm = bufr;
2474       icolm = bufc;
2475     } else {
2476       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2477       irowm = bufr;
2478       icolm = bufc;
2479     }
2480     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2481     else irowm = irow;
2482     if (mat->cmap->mapping) {
2483       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2484         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2485       } else icolm = irowm;
2486     } else icolm = icol;
2487     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2488     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2489   }
2490   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2491   PetscFunctionReturn(PETSC_SUCCESS);
2492 }
2493 
2494 /*@
2495    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2496 
2497    Collective
2498 
2499    Input Parameters:
2500 +  mat - the matrix
2501 -  x   - the vector to be multiplied
2502 
2503    Output Parameter:
2504 .  y - the result
2505 
2506    Level: developer
2507 
2508    Note:
2509    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2510    call `MatMultDiagonalBlock`(A,y,y).
2511 
2512 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2513 @*/
2514 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2515 {
2516   PetscFunctionBegin;
2517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2518   PetscValidType(mat, 1);
2519   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2520   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2521 
2522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2524   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2525   MatCheckPreallocated(mat, 1);
2526 
2527   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2528   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2529   PetscFunctionReturn(PETSC_SUCCESS);
2530 }
2531 
2532 /*@
2533    MatMult - Computes the matrix-vector product, y = Ax.
2534 
2535    Neighbor-wise Collective
2536 
2537    Input Parameters:
2538 +  mat - the matrix
2539 -  x   - the vector to be multiplied
2540 
2541    Output Parameter:
2542 .  y - the result
2543 
2544    Level: beginner
2545 
2546    Note:
2547    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2548    call `MatMult`(A,y,y).
2549 
2550 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2551 @*/
2552 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2553 {
2554   PetscFunctionBegin;
2555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2556   PetscValidType(mat, 1);
2557   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2558   VecCheckAssembled(x);
2559   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2560   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2561   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2562   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2563   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);
2564   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);
2565   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);
2566   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);
2567   PetscCall(VecSetErrorIfLocked(y, 3));
2568   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2569   MatCheckPreallocated(mat, 1);
2570 
2571   PetscCall(VecLockReadPush(x));
2572   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2573   PetscUseTypeMethod(mat, mult, x, y);
2574   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2575   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2576   PetscCall(VecLockReadPop(x));
2577   PetscFunctionReturn(PETSC_SUCCESS);
2578 }
2579 
2580 /*@
2581    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2582 
2583    Neighbor-wise Collective
2584 
2585    Input Parameters:
2586 +  mat - the matrix
2587 -  x   - the vector to be multiplied
2588 
2589    Output Parameter:
2590 .  y - the result
2591 
2592    Level: beginner
2593 
2594    Notes:
2595    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2596    call `MatMultTranspose`(A,y,y).
2597 
2598    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2599    use `MatMultHermitianTranspose()`
2600 
2601 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2602 @*/
2603 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2604 {
2605   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2606 
2607   PetscFunctionBegin;
2608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2609   PetscValidType(mat, 1);
2610   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2611   VecCheckAssembled(x);
2612   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2613 
2614   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2615   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2616   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2617   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);
2618   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);
2619   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);
2620   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);
2621   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2622   MatCheckPreallocated(mat, 1);
2623 
2624   if (!mat->ops->multtranspose) {
2625     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2626     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);
2627   } else op = mat->ops->multtranspose;
2628   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2629   PetscCall(VecLockReadPush(x));
2630   PetscCall((*op)(mat, x, y));
2631   PetscCall(VecLockReadPop(x));
2632   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2633   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2634   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2635   PetscFunctionReturn(PETSC_SUCCESS);
2636 }
2637 
2638 /*@
2639    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2640 
2641    Neighbor-wise Collective
2642 
2643    Input Parameters:
2644 +  mat - the matrix
2645 -  x   - the vector to be multilplied
2646 
2647    Output Parameter:
2648 .  y - the result
2649 
2650    Level: beginner
2651 
2652    Notes:
2653    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2654    call `MatMultHermitianTranspose`(A,y,y).
2655 
2656    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2657 
2658    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2659 
2660 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2661 @*/
2662 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2663 {
2664   PetscFunctionBegin;
2665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2666   PetscValidType(mat, 1);
2667   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2668   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2669 
2670   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2671   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2672   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2673   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);
2674   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);
2675   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);
2676   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);
2677   MatCheckPreallocated(mat, 1);
2678 
2679   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2680 #if defined(PETSC_USE_COMPLEX)
2681   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2682     PetscCall(VecLockReadPush(x));
2683     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2684     else PetscUseTypeMethod(mat, mult, x, y);
2685     PetscCall(VecLockReadPop(x));
2686   } else {
2687     Vec w;
2688     PetscCall(VecDuplicate(x, &w));
2689     PetscCall(VecCopy(x, w));
2690     PetscCall(VecConjugate(w));
2691     PetscCall(MatMultTranspose(mat, w, y));
2692     PetscCall(VecDestroy(&w));
2693     PetscCall(VecConjugate(y));
2694   }
2695   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2696 #else
2697   PetscCall(MatMultTranspose(mat, x, y));
2698 #endif
2699   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2700   PetscFunctionReturn(PETSC_SUCCESS);
2701 }
2702 
2703 /*@
2704     MatMultAdd -  Computes v3 = v2 + A * v1.
2705 
2706     Neighbor-wise Collective
2707 
2708     Input Parameters:
2709 +   mat - the matrix
2710 .   v1 - the vector to be multiplied by `mat`
2711 -   v2 - the vector to be added to the result
2712 
2713     Output Parameter:
2714 .   v3 - the result
2715 
2716     Level: beginner
2717 
2718     Note:
2719     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2720     call `MatMultAdd`(A,v1,v2,v1).
2721 
2722 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2723 @*/
2724 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2725 {
2726   PetscFunctionBegin;
2727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2728   PetscValidType(mat, 1);
2729   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2730   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2731   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2732 
2733   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2735   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);
2736   /* 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);
2737      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); */
2738   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);
2739   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);
2740   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2741   MatCheckPreallocated(mat, 1);
2742 
2743   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2744   PetscCall(VecLockReadPush(v1));
2745   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2746   PetscCall(VecLockReadPop(v1));
2747   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2748   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2749   PetscFunctionReturn(PETSC_SUCCESS);
2750 }
2751 
2752 /*@
2753    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2754 
2755    Neighbor-wise Collective
2756 
2757    Input Parameters:
2758 +  mat - the matrix
2759 .  v1 - the vector to be multiplied by the transpose of the matrix
2760 -  v2 - the vector to be added to the result
2761 
2762    Output Parameter:
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 - the vector to be multiplied by the Hermitian transpose
2810 -  v2 - the vector to be added to the result
2811 
2812    Output Parameter:
2813 .  v3 - the result
2814 
2815    Level: beginner
2816 
2817    Note:
2818    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2819    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2820 
2821 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2822 @*/
2823 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2824 {
2825   PetscFunctionBegin;
2826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2827   PetscValidType(mat, 1);
2828   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2829   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2830   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2831 
2832   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2833   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2834   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2835   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);
2836   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);
2837   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);
2838   MatCheckPreallocated(mat, 1);
2839 
2840   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2841   PetscCall(VecLockReadPush(v1));
2842   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2843   else {
2844     Vec w, z;
2845     PetscCall(VecDuplicate(v1, &w));
2846     PetscCall(VecCopy(v1, w));
2847     PetscCall(VecConjugate(w));
2848     PetscCall(VecDuplicate(v3, &z));
2849     PetscCall(MatMultTranspose(mat, w, z));
2850     PetscCall(VecDestroy(&w));
2851     PetscCall(VecConjugate(z));
2852     if (v2 != v3) {
2853       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2854     } else {
2855       PetscCall(VecAXPY(v3, 1.0, z));
2856     }
2857     PetscCall(VecDestroy(&z));
2858   }
2859   PetscCall(VecLockReadPop(v1));
2860   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2861   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2862   PetscFunctionReturn(PETSC_SUCCESS);
2863 }
2864 
2865 /*@C
2866    MatGetFactorType - gets the type of factorization it is
2867 
2868    Not Collective
2869 
2870    Input Parameter:
2871 .  mat - the matrix
2872 
2873    Output Parameter:
2874 .  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`
2875 
2876    Level: intermediate
2877 
2878 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2879           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2880 @*/
2881 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2882 {
2883   PetscFunctionBegin;
2884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2885   PetscValidType(mat, 1);
2886   PetscValidPointer(t, 2);
2887   *t = mat->factortype;
2888   PetscFunctionReturn(PETSC_SUCCESS);
2889 }
2890 
2891 /*@C
2892    MatSetFactorType - sets the type of factorization it is
2893 
2894    Logically Collective
2895 
2896    Input Parameters:
2897 +  mat - the matrix
2898 -  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`
2899 
2900    Level: intermediate
2901 
2902 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2903           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2904 @*/
2905 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2906 {
2907   PetscFunctionBegin;
2908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2909   PetscValidType(mat, 1);
2910   mat->factortype = t;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915    MatGetInfo - Returns information about matrix storage (number of
2916    nonzeros, memory, etc.).
2917 
2918    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2919 
2920    Input Parameters:
2921 +  mat - the matrix
2922 -  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)
2923 
2924    Output Parameter:
2925 .  info - matrix information context
2926 
2927    Notes:
2928    The `MatInfo` context contains a variety of matrix data, including
2929    number of nonzeros allocated and used, number of mallocs during
2930    matrix assembly, etc.  Additional information for factored matrices
2931    is provided (such as the fill ratio, number of mallocs during
2932    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2933    when using the runtime options
2934 $       -info -mat_view ::ascii_info
2935 
2936    Example:
2937    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2938    data within the MatInfo context.  For example,
2939 .vb
2940       MatInfo info;
2941       Mat     A;
2942       double  mal, nz_a, nz_u;
2943 
2944       MatGetInfo(A,MAT_LOCAL,&info);
2945       mal  = info.mallocs;
2946       nz_a = info.nz_allocated;
2947 .ve
2948 
2949    Fortran users should declare info as a double precision
2950    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2951    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2952    a complete list of parameter names.
2953 .vb
2954       double  precision info(MAT_INFO_SIZE)
2955       double  precision mal, nz_a
2956       Mat     A
2957       integer ierr
2958 
2959       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2960       mal = info(MAT_INFO_MALLOCS)
2961       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2962 .ve
2963 
2964     Level: intermediate
2965 
2966     Developer Note:
2967     The Fortran interface is not autogenerated as the
2968     interface definition cannot be generated correctly [due to `MatInfo` argument]
2969 
2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2971 @*/
2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2973 {
2974   PetscFunctionBegin;
2975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2976   PetscValidType(mat, 1);
2977   PetscValidPointer(info, 3);
2978   MatCheckPreallocated(mat, 1);
2979   PetscUseTypeMethod(mat, getinfo, flag, info);
2980   PetscFunctionReturn(PETSC_SUCCESS);
2981 }
2982 
2983 /*
2984    This is used by external packages where it is not easy to get the info from the actual
2985    matrix factorization.
2986 */
2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2988 {
2989   PetscFunctionBegin;
2990   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2991   PetscFunctionReturn(PETSC_SUCCESS);
2992 }
2993 
2994 /*@C
2995    MatLUFactor - Performs in-place LU factorization of matrix.
2996 
2997    Collective
2998 
2999    Input Parameters:
3000 +  mat - the matrix
3001 .  row - row permutation
3002 .  col - column permutation
3003 -  info - options for factorization, includes
3004 .vb
3005           fill - expected fill as ratio of original fill.
3006           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3007                    Run with the option -info to determine an optimal value to use
3008 .ve
3009    Level: developer
3010 
3011    Notes:
3012    Most users should employ the `KSP` interface for linear solvers
3013    instead of working directly with matrix algebra routines such as this.
3014    See, e.g., `KSPCreate()`.
3015 
3016    This changes the state of the matrix to a factored matrix; it cannot be used
3017    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3018 
3019    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3020    when not using `KSP`.
3021 
3022    Developer Note:
3023    The Fortran interface is not autogenerated as the
3024    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3025 
3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3027           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3028 @*/
3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3030 {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3037   if (info) PetscValidPointer(info, 4);
3038   PetscValidType(mat, 1);
3039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3041   MatCheckPreallocated(mat, 1);
3042   if (!info) {
3043     PetscCall(MatFactorInfoInitialize(&tinfo));
3044     info = &tinfo;
3045   }
3046 
3047   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3048   PetscUseTypeMethod(mat, lufactor, row, col, info);
3049   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055    MatILUFactor - Performs in-place ILU factorization of matrix.
3056 
3057    Collective
3058 
3059    Input Parameters:
3060 +  mat - the matrix
3061 .  row - row permutation
3062 .  col - column permutation
3063 -  info - structure containing
3064 .vb
3065       levels - number of levels of fill.
3066       expected fill - as ratio of original fill.
3067       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3068                 missing diagonal entries)
3069 .ve
3070 
3071    Level: developer
3072 
3073    Notes:
3074    Most users should employ the `KSP` interface for linear solvers
3075    instead of working directly with matrix algebra routines such as this.
3076    See, e.g., `KSPCreate()`.
3077 
3078    Probably really in-place only when level of fill is zero, otherwise allocates
3079    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3080    when not using `KSP`.
3081 
3082    Developer Note:
3083    The Fortran interface is not autogenerated as the
3084    interface definition cannot be generated correctly [due to MatFactorInfo]
3085 
3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3087 @*/
3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3089 {
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3092   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3093   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3094   PetscValidPointer(info, 4);
3095   PetscValidType(mat, 1);
3096   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3099   MatCheckPreallocated(mat, 1);
3100 
3101   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3102   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3103   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3105   PetscFunctionReturn(PETSC_SUCCESS);
3106 }
3107 
3108 /*@C
3109    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3110    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3111 
3112    Collective
3113 
3114    Input Parameters:
3115 +  fact - the factor matrix obtained with `MatGetFactor()`
3116 .  mat - the matrix
3117 .  row - the row permutation
3118 .  col - the column permutation
3119 -  info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123 .ve
3124 
3125    Level: developer
3126 
3127    Notes:
3128     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3129 
3130    Most users should employ the simplified `KSP` interface for linear solvers
3131    instead of working directly with matrix algebra routines such as this.
3132    See, e.g., `KSPCreate()`.
3133 
3134    Developer Note:
3135    The Fortran interface is not autogenerated as the
3136    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137 
3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139 @*/
3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141 {
3142   MatFactorInfo tinfo;
3143 
3144   PetscFunctionBegin;
3145   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3147   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3148   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3149   if (info) PetscValidPointer(info, 5);
3150   PetscValidType(fact, 1);
3151   PetscValidType(mat, 2);
3152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3153   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3154   MatCheckPreallocated(mat, 2);
3155   if (!info) {
3156     PetscCall(MatFactorInfoInitialize(&tinfo));
3157     info = &tinfo;
3158   }
3159 
3160   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3161   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3162   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3163   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3164   PetscFunctionReturn(PETSC_SUCCESS);
3165 }
3166 
3167 /*@C
3168    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3169    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3170 
3171    Collective
3172 
3173    Input Parameters:
3174 +  fact - the factor matrix obtained with `MatGetFactor()`
3175 .  mat - the matrix
3176 -  info - options for factorization
3177 
3178    Level: developer
3179 
3180    Notes:
3181    See `MatLUFactor()` for in-place factorization.  See
3182    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3183 
3184    Most users should employ the `KSP` interface for linear solvers
3185    instead of working directly with matrix algebra routines such as this.
3186    See, e.g., `KSPCreate()`.
3187 
3188     Developer Note:
3189     The Fortran interface is not autogenerated as the
3190     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3191 
3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3193 @*/
3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3195 {
3196   MatFactorInfo tinfo;
3197 
3198   PetscFunctionBegin;
3199   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3201   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3202   PetscValidType(fact, 1);
3203   PetscValidType(mat, 2);
3204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3205   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,
3206              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3207 
3208   MatCheckPreallocated(mat, 2);
3209   if (!info) {
3210     PetscCall(MatFactorInfoInitialize(&tinfo));
3211     info = &tinfo;
3212   }
3213 
3214   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3215   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3216   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3217   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3218   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3219   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3220   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3221   PetscFunctionReturn(PETSC_SUCCESS);
3222 }
3223 
3224 /*@C
3225    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3226    symmetric matrix.
3227 
3228    Collective
3229 
3230    Input Parameters:
3231 +  mat - the matrix
3232 .  perm - row and column permutations
3233 -  f - expected fill as ratio of original fill
3234 
3235    Level: developer
3236 
3237    Notes:
3238    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3239    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3240 
3241    Most users should employ the `KSP` interface for linear solvers
3242    instead of working directly with matrix algebra routines such as this.
3243    See, e.g., `KSPCreate()`.
3244 
3245    Developer Note:
3246    The Fortran interface is not autogenerated as the
3247    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3248 
3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3250           `MatGetOrdering()`
3251 @*/
3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3253 {
3254   MatFactorInfo tinfo;
3255 
3256   PetscFunctionBegin;
3257   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3258   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3259   if (info) PetscValidPointer(info, 3);
3260   PetscValidType(mat, 1);
3261   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3262   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3263   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3264   MatCheckPreallocated(mat, 1);
3265   if (!info) {
3266     PetscCall(MatFactorInfoInitialize(&tinfo));
3267     info = &tinfo;
3268   }
3269 
3270   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3271   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3272   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3273   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3274   PetscFunctionReturn(PETSC_SUCCESS);
3275 }
3276 
3277 /*@C
3278    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3279    of a symmetric matrix.
3280 
3281    Collective
3282 
3283    Input Parameters:
3284 +  fact - the factor matrix obtained with `MatGetFactor()`
3285 .  mat - the matrix
3286 .  perm - row and column permutations
3287 -  info - options for factorization, includes
3288 .vb
3289           fill - expected fill as ratio of original fill.
3290           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3291                    Run with the option -info to determine an optimal value to use
3292 .ve
3293 
3294    Level: developer
3295 
3296    Notes:
3297    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3298    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3299 
3300    Most users should employ the `KSP` interface for linear solvers
3301    instead of working directly with matrix algebra routines such as this.
3302    See, e.g., `KSPCreate()`.
3303 
3304    Developer Note:
3305    The Fortran interface is not autogenerated as the
3306    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3307 
3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3309           `MatGetOrdering()`
3310 @*/
3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3312 {
3313   MatFactorInfo tinfo;
3314 
3315   PetscFunctionBegin;
3316   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3318   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3319   if (info) PetscValidPointer(info, 4);
3320   PetscValidType(fact, 1);
3321   PetscValidType(mat, 2);
3322   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3324   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3325   MatCheckPreallocated(mat, 2);
3326   if (!info) {
3327     PetscCall(MatFactorInfoInitialize(&tinfo));
3328     info = &tinfo;
3329   }
3330 
3331   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3332   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3333   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3334   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3335   PetscFunctionReturn(PETSC_SUCCESS);
3336 }
3337 
3338 /*@C
3339    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3340    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3341    `MatCholeskyFactorSymbolic()`.
3342 
3343    Collective
3344 
3345    Input Parameters:
3346 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3347 .  mat - the initial matrix that is to be factored
3348 -  info - options for factorization
3349 
3350    Level: developer
3351 
3352    Note:
3353    Most users should employ the `KSP` interface for linear solvers
3354    instead of working directly with matrix algebra routines such as this.
3355    See, e.g., `KSPCreate()`.
3356 
3357    Developer Note:
3358    The Fortran interface is not autogenerated as the
3359    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3360 
3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3362 @*/
3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3364 {
3365   MatFactorInfo tinfo;
3366 
3367   PetscFunctionBegin;
3368   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3370   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3371   PetscValidType(fact, 1);
3372   PetscValidType(mat, 2);
3373   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3374   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,
3375              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3376   MatCheckPreallocated(mat, 2);
3377   if (!info) {
3378     PetscCall(MatFactorInfoInitialize(&tinfo));
3379     info = &tinfo;
3380   }
3381 
3382   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3383   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3384   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3385   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3386   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3387   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3388   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3389   PetscFunctionReturn(PETSC_SUCCESS);
3390 }
3391 
3392 /*@
3393    MatQRFactor - Performs in-place QR factorization of matrix.
3394 
3395    Collective
3396 
3397    Input Parameters:
3398 +  mat - the matrix
3399 .  col - column permutation
3400 -  info - options for factorization, includes
3401 .vb
3402           fill - expected fill as ratio of original fill.
3403           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3404                    Run with the option -info to determine an optimal value to use
3405 .ve
3406 
3407    Level: developer
3408 
3409    Notes:
3410    Most users should employ the `KSP` interface for linear solvers
3411    instead of working directly with matrix algebra routines such as this.
3412    See, e.g., `KSPCreate()`.
3413 
3414    This changes the state of the matrix to a factored matrix; it cannot be used
3415    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3416 
3417    Developer Note:
3418    The Fortran interface is not autogenerated as the
3419    interface definition cannot be generated correctly [due to MatFactorInfo]
3420 
3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3422           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3423 @*/
3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3425 {
3426   PetscFunctionBegin;
3427   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3428   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3429   if (info) PetscValidPointer(info, 3);
3430   PetscValidType(mat, 1);
3431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3433   MatCheckPreallocated(mat, 1);
3434   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3435   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3436   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3437   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3438   PetscFunctionReturn(PETSC_SUCCESS);
3439 }
3440 
3441 /*@
3442    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3443    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3444 
3445    Collective
3446 
3447    Input Parameters:
3448 +  fact - the factor matrix obtained with `MatGetFactor()`
3449 .  mat - the matrix
3450 .  col - column permutation
3451 -  info - options for factorization, includes
3452 .vb
3453           fill - expected fill as ratio of original fill.
3454           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3455                    Run with the option -info to determine an optimal value to use
3456 .ve
3457 
3458    Level: developer
3459 
3460    Note:
3461    Most users should employ the `KSP` interface for linear solvers
3462    instead of working directly with matrix algebra routines such as this.
3463    See, e.g., `KSPCreate()`.
3464 
3465    Developer Note:
3466    The Fortran interface is not autogenerated as the
3467    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3468 
3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3470 @*/
3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3472 {
3473   MatFactorInfo tinfo;
3474 
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3478   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3479   if (info) PetscValidPointer(info, 4);
3480   PetscValidType(fact, 1);
3481   PetscValidType(mat, 2);
3482   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3483   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3484   MatCheckPreallocated(mat, 2);
3485   if (!info) {
3486     PetscCall(MatFactorInfoInitialize(&tinfo));
3487     info = &tinfo;
3488   }
3489 
3490   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3491   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3492   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3493   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3494   PetscFunctionReturn(PETSC_SUCCESS);
3495 }
3496 
3497 /*@
3498    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3499    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3500 
3501    Collective
3502 
3503    Input Parameters:
3504 +  fact - the factor matrix obtained with `MatGetFactor()`
3505 .  mat - the matrix
3506 -  info - options for factorization
3507 
3508    Level: developer
3509 
3510    Notes:
3511    See `MatQRFactor()` for in-place factorization.
3512 
3513    Most users should employ the `KSP` interface for linear solvers
3514    instead of working directly with matrix algebra routines such as this.
3515    See, e.g., `KSPCreate()`.
3516 
3517    Developer Note:
3518    The Fortran interface is not autogenerated as the
3519    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3520 
3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3522 @*/
3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3524 {
3525   MatFactorInfo tinfo;
3526 
3527   PetscFunctionBegin;
3528   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3530   PetscValidType(fact, 1);
3531   PetscValidType(mat, 2);
3532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3533   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,
3534              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3535 
3536   MatCheckPreallocated(mat, 2);
3537   if (!info) {
3538     PetscCall(MatFactorInfoInitialize(&tinfo));
3539     info = &tinfo;
3540   }
3541 
3542   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3543   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3544   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3545   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3546   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3547   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3548   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3549   PetscFunctionReturn(PETSC_SUCCESS);
3550 }
3551 
3552 /*@
3553    MatSolve - Solves A x = b, given a factored matrix.
3554 
3555    Neighbor-wise Collective
3556 
3557    Input Parameters:
3558 +  mat - the factored matrix
3559 -  b - the right-hand-side vector
3560 
3561    Output Parameter:
3562 .  x - the result vector
3563 
3564    Level: developer
3565 
3566    Notes:
3567    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3568    call `MatSolve`(A,x,x).
3569 
3570    Most users should employ the `KSP` interface for linear solvers
3571    instead of working directly with matrix algebra routines such as this.
3572    See, e.g., `KSPCreate()`.
3573 
3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3575 @*/
3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3577 {
3578   PetscFunctionBegin;
3579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3580   PetscValidType(mat, 1);
3581   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3582   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3583   PetscCheckSameComm(mat, 1, b, 2);
3584   PetscCheckSameComm(mat, 1, x, 3);
3585   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3586   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);
3587   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);
3588   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);
3589   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3590   MatCheckPreallocated(mat, 1);
3591 
3592   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3593   if (mat->factorerrortype) {
3594     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3595     PetscCall(VecSetInf(x));
3596   } else PetscUseTypeMethod(mat, solve, b, x);
3597   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3598   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3599   PetscFunctionReturn(PETSC_SUCCESS);
3600 }
3601 
3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3603 {
3604   Vec      b, x;
3605   PetscInt N, i;
3606   PetscErrorCode (*f)(Mat, Vec, Vec);
3607   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3608 
3609   PetscFunctionBegin;
3610   if (A->factorerrortype) {
3611     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3612     PetscCall(MatSetInf(X));
3613     PetscFunctionReturn(PETSC_SUCCESS);
3614   }
3615   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3616   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3617   PetscCall(MatBoundToCPU(A, &Abound));
3618   if (!Abound) {
3619     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3620     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3621   }
3622 #if defined(PETSC_HAVE_CUDA)
3623   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3624   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3625 #elif (PETSC_HAVE_HIP)
3626   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3627   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3628 #endif
3629   PetscCall(MatGetSize(B, NULL, &N));
3630   for (i = 0; i < N; i++) {
3631     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3632     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3633     PetscCall((*f)(A, b, x));
3634     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3635     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3636   }
3637   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3638   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3639   PetscFunctionReturn(PETSC_SUCCESS);
3640 }
3641 
3642 /*@
3643    MatMatSolve - Solves A X = B, given a factored matrix.
3644 
3645    Neighbor-wise Collective
3646 
3647    Input Parameters:
3648 +  A - the factored matrix
3649 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3650 
3651    Output Parameter:
3652 .  X - the result matrix (dense matrix)
3653 
3654    Level: developer
3655 
3656    Note:
3657    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3658    otherwise, `B` and `X` cannot be the same.
3659 
3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3661 @*/
3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3663 {
3664   PetscFunctionBegin;
3665   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3666   PetscValidType(A, 1);
3667   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3668   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3669   PetscCheckSameComm(A, 1, B, 2);
3670   PetscCheckSameComm(A, 1, X, 3);
3671   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);
3672   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);
3673   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");
3674   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3675   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3676   MatCheckPreallocated(A, 1);
3677 
3678   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3679   if (!A->ops->matsolve) {
3680     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3681     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3682   } else PetscUseTypeMethod(A, matsolve, B, X);
3683   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3684   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3685   PetscFunctionReturn(PETSC_SUCCESS);
3686 }
3687 
3688 /*@
3689    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3690 
3691    Neighbor-wise Collective
3692 
3693    Input Parameters:
3694 +  A - the factored matrix
3695 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3696 
3697    Output Parameter:
3698 .  X - the result matrix (dense matrix)
3699 
3700    Level: developer
3701 
3702    Note:
3703    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3704    call `MatMatSolveTranspose`(A,X,X).
3705 
3706 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3707 @*/
3708 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3709 {
3710   PetscFunctionBegin;
3711   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3712   PetscValidType(A, 1);
3713   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3714   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3715   PetscCheckSameComm(A, 1, B, 2);
3716   PetscCheckSameComm(A, 1, X, 3);
3717   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3718   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);
3719   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);
3720   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);
3721   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");
3722   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3723   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3724   MatCheckPreallocated(A, 1);
3725 
3726   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3727   if (!A->ops->matsolvetranspose) {
3728     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3729     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3730   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3731   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3732   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3733   PetscFunctionReturn(PETSC_SUCCESS);
3734 }
3735 
3736 /*@
3737    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3738 
3739    Neighbor-wise Collective
3740 
3741    Input Parameters:
3742 +  A - the factored matrix
3743 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3744 
3745    Output Parameter:
3746 .  X - the result matrix (dense matrix)
3747 
3748    Level: developer
3749 
3750    Note:
3751    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
3752    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3753 
3754 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3755 @*/
3756 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3757 {
3758   PetscFunctionBegin;
3759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3760   PetscValidType(A, 1);
3761   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3762   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3763   PetscCheckSameComm(A, 1, Bt, 2);
3764   PetscCheckSameComm(A, 1, X, 3);
3765 
3766   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3767   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);
3768   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);
3769   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");
3770   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3771   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3772   MatCheckPreallocated(A, 1);
3773 
3774   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3775   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3776   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3777   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3778   PetscFunctionReturn(PETSC_SUCCESS);
3779 }
3780 
3781 /*@
3782    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3783                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3784 
3785    Neighbor-wise Collective
3786 
3787    Input Parameters:
3788 +  mat - the factored matrix
3789 -  b - the right-hand-side vector
3790 
3791    Output Parameter:
3792 .  x - the result vector
3793 
3794    Level: developer
3795 
3796    Notes:
3797    `MatSolve()` should be used for most applications, as it performs
3798    a forward solve followed by a backward solve.
3799 
3800    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3801    call `MatForwardSolve`(A,x,x).
3802 
3803    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3804    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3805    `MatForwardSolve()` solves U^T*D y = b, and
3806    `MatBackwardSolve()` solves U x = y.
3807    Thus they do not provide a symmetric preconditioner.
3808 
3809 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3810 @*/
3811 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3812 {
3813   PetscFunctionBegin;
3814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3815   PetscValidType(mat, 1);
3816   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3817   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3818   PetscCheckSameComm(mat, 1, b, 2);
3819   PetscCheckSameComm(mat, 1, x, 3);
3820   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3821   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);
3822   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);
3823   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);
3824   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3825   MatCheckPreallocated(mat, 1);
3826 
3827   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3828   PetscUseTypeMethod(mat, forwardsolve, b, x);
3829   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3830   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3831   PetscFunctionReturn(PETSC_SUCCESS);
3832 }
3833 
3834 /*@
3835    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3836                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3837 
3838    Neighbor-wise Collective
3839 
3840    Input Parameters:
3841 +  mat - the factored matrix
3842 -  b - the right-hand-side vector
3843 
3844    Output Parameter:
3845 .  x - the result vector
3846 
3847    Level: developer
3848 
3849    Notes:
3850    `MatSolve()` should be used for most applications, as it performs
3851    a forward solve followed by a backward solve.
3852 
3853    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3854    call `MatBackwardSolve`(A,x,x).
3855 
3856    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3857    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3858    `MatForwardSolve()` solves U^T*D y = b, and
3859    `MatBackwardSolve()` solves U x = y.
3860    Thus they do not provide a symmetric preconditioner.
3861 
3862 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3863 @*/
3864 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3865 {
3866   PetscFunctionBegin;
3867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3868   PetscValidType(mat, 1);
3869   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3870   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3871   PetscCheckSameComm(mat, 1, b, 2);
3872   PetscCheckSameComm(mat, 1, x, 3);
3873   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3874   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);
3875   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);
3876   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);
3877   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3878   MatCheckPreallocated(mat, 1);
3879 
3880   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3881   PetscUseTypeMethod(mat, backwardsolve, b, x);
3882   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3883   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3884   PetscFunctionReturn(PETSC_SUCCESS);
3885 }
3886 
3887 /*@
3888    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3889 
3890    Neighbor-wise Collective
3891 
3892    Input Parameters:
3893 +  mat - the factored matrix
3894 .  b - the right-hand-side vector
3895 -  y - the vector to be added to
3896 
3897    Output Parameter:
3898 .  x - the result vector
3899 
3900    Level: developer
3901 
3902    Note:
3903    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3904    call `MatSolveAdd`(A,x,y,x).
3905 
3906 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3907 @*/
3908 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3909 {
3910   PetscScalar one = 1.0;
3911   Vec         tmp;
3912 
3913   PetscFunctionBegin;
3914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3915   PetscValidType(mat, 1);
3916   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3917   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3918   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3919   PetscCheckSameComm(mat, 1, b, 2);
3920   PetscCheckSameComm(mat, 1, y, 3);
3921   PetscCheckSameComm(mat, 1, x, 4);
3922   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3923   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);
3924   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);
3925   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);
3926   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);
3927   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);
3928   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3929   MatCheckPreallocated(mat, 1);
3930 
3931   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3932   if (mat->factorerrortype) {
3933     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3934     PetscCall(VecSetInf(x));
3935   } else if (mat->ops->solveadd) {
3936     PetscUseTypeMethod(mat, solveadd, b, y, x);
3937   } else {
3938     /* do the solve then the add manually */
3939     if (x != y) {
3940       PetscCall(MatSolve(mat, b, x));
3941       PetscCall(VecAXPY(x, one, y));
3942     } else {
3943       PetscCall(VecDuplicate(x, &tmp));
3944       PetscCall(VecCopy(x, tmp));
3945       PetscCall(MatSolve(mat, b, x));
3946       PetscCall(VecAXPY(x, one, tmp));
3947       PetscCall(VecDestroy(&tmp));
3948     }
3949   }
3950   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3951   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3952   PetscFunctionReturn(PETSC_SUCCESS);
3953 }
3954 
3955 /*@
3956    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3957 
3958    Neighbor-wise Collective
3959 
3960    Input Parameters:
3961 +  mat - the factored matrix
3962 -  b - the right-hand-side vector
3963 
3964    Output Parameter:
3965 .  x - the result vector
3966 
3967    Level: developer
3968 
3969    Notes:
3970    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3971    call `MatSolveTranspose`(A,x,x).
3972 
3973    Most users should employ the `KSP` interface for linear solvers
3974    instead of working directly with matrix algebra routines such as this.
3975    See, e.g., `KSPCreate()`.
3976 
3977 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3978 @*/
3979 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3980 {
3981   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3982 
3983   PetscFunctionBegin;
3984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3985   PetscValidType(mat, 1);
3986   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3987   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3988   PetscCheckSameComm(mat, 1, b, 2);
3989   PetscCheckSameComm(mat, 1, x, 3);
3990   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3991   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);
3992   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);
3993   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3994   MatCheckPreallocated(mat, 1);
3995   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3996   if (mat->factorerrortype) {
3997     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3998     PetscCall(VecSetInf(x));
3999   } else {
4000     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4001     PetscCall((*f)(mat, b, x));
4002   }
4003   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4004   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4005   PetscFunctionReturn(PETSC_SUCCESS);
4006 }
4007 
4008 /*@
4009    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4010                       factored matrix.
4011 
4012    Neighbor-wise Collective
4013 
4014    Input Parameters:
4015 +  mat - the factored matrix
4016 .  b - the right-hand-side vector
4017 -  y - the vector to be added to
4018 
4019    Output Parameter:
4020 .  x - the result vector
4021 
4022    Level: developer
4023 
4024    Note:
4025    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4026    call `MatSolveTransposeAdd`(A,x,y,x).
4027 
4028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4029 @*/
4030 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4031 {
4032   PetscScalar one = 1.0;
4033   Vec         tmp;
4034   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4035 
4036   PetscFunctionBegin;
4037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4038   PetscValidType(mat, 1);
4039   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4040   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4041   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4042   PetscCheckSameComm(mat, 1, b, 2);
4043   PetscCheckSameComm(mat, 1, y, 3);
4044   PetscCheckSameComm(mat, 1, x, 4);
4045   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4046   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);
4047   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);
4048   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);
4049   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);
4050   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4051   MatCheckPreallocated(mat, 1);
4052 
4053   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4054   if (mat->factorerrortype) {
4055     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4056     PetscCall(VecSetInf(x));
4057   } else if (f) {
4058     PetscCall((*f)(mat, b, y, x));
4059   } else {
4060     /* do the solve then the add manually */
4061     if (x != y) {
4062       PetscCall(MatSolveTranspose(mat, b, x));
4063       PetscCall(VecAXPY(x, one, y));
4064     } else {
4065       PetscCall(VecDuplicate(x, &tmp));
4066       PetscCall(VecCopy(x, tmp));
4067       PetscCall(MatSolveTranspose(mat, b, x));
4068       PetscCall(VecAXPY(x, one, tmp));
4069       PetscCall(VecDestroy(&tmp));
4070     }
4071   }
4072   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4073   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4074   PetscFunctionReturn(PETSC_SUCCESS);
4075 }
4076 
4077 /*@
4078    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4079 
4080    Neighbor-wise Collective
4081 
4082    Input Parameters:
4083 +  mat - the matrix
4084 .  b - the right hand side
4085 .  omega - the relaxation factor
4086 .  flag - flag indicating the type of SOR (see below)
4087 .  shift -  diagonal shift
4088 .  its - the number of iterations
4089 -  lits - the number of local iterations
4090 
4091    Output Parameter:
4092 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4093 
4094    SOR Flags:
4095 +     `SOR_FORWARD_SWEEP` - forward SOR
4096 .     `SOR_BACKWARD_SWEEP` - backward SOR
4097 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4098 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4099 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4100 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4101 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4102 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4103          upper/lower triangular part of matrix to
4104          vector (with omega)
4105 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4106 
4107    Level: developer
4108 
4109    Notes:
4110    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4111    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4112    on each processor.
4113 
4114    Application programmers will not generally use `MatSOR()` directly,
4115    but instead will employ the `KSP`/`PC` interface.
4116 
4117    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4118 
4119    Most users should employ the `KSP` interface for linear solvers
4120    instead of working directly with matrix algebra routines such as this.
4121    See, e.g., `KSPCreate()`.
4122 
4123    Vectors `x` and `b` CANNOT be the same
4124 
4125    The flags are implemented as bitwise inclusive or operations.
4126    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4127    to specify a zero initial guess for SSOR.
4128 
4129    Developer Note:
4130    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4131 
4132 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4133 @*/
4134 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4135 {
4136   PetscFunctionBegin;
4137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4138   PetscValidType(mat, 1);
4139   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4140   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4141   PetscCheckSameComm(mat, 1, b, 2);
4142   PetscCheckSameComm(mat, 1, x, 8);
4143   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4144   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4145   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);
4146   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);
4147   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);
4148   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4149   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4150   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4151 
4152   MatCheckPreallocated(mat, 1);
4153   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4154   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4155   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4156   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4157   PetscFunctionReturn(PETSC_SUCCESS);
4158 }
4159 
4160 /*
4161       Default matrix copy routine.
4162 */
4163 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4164 {
4165   PetscInt           i, rstart = 0, rend = 0, nz;
4166   const PetscInt    *cwork;
4167   const PetscScalar *vwork;
4168 
4169   PetscFunctionBegin;
4170   if (B->assembled) PetscCall(MatZeroEntries(B));
4171   if (str == SAME_NONZERO_PATTERN) {
4172     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4173     for (i = rstart; i < rend; i++) {
4174       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4175       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4176       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4177     }
4178   } else {
4179     PetscCall(MatAYPX(B, 0.0, A, str));
4180   }
4181   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4182   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4183   PetscFunctionReturn(PETSC_SUCCESS);
4184 }
4185 
4186 /*@
4187    MatCopy - Copies a matrix to another matrix.
4188 
4189    Collective
4190 
4191    Input Parameters:
4192 +  A - the matrix
4193 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4194 
4195    Output Parameter:
4196 .  B - where the copy is put
4197 
4198    Level: intermediate
4199 
4200    Notes:
4201    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4202 
4203    `MatCopy()` copies the matrix entries of a matrix to another existing
4204    matrix (after first zeroing the second matrix).  A related routine is
4205    `MatConvert()`, which first creates a new matrix and then copies the data.
4206 
4207 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4208 @*/
4209 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4210 {
4211   PetscInt i;
4212 
4213   PetscFunctionBegin;
4214   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4215   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4216   PetscValidType(A, 1);
4217   PetscValidType(B, 2);
4218   PetscCheckSameComm(A, 1, B, 2);
4219   MatCheckPreallocated(B, 2);
4220   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4221   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4222   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,
4223              A->cmap->N, B->cmap->N);
4224   MatCheckPreallocated(A, 1);
4225   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4226 
4227   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4228   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4229   else PetscCall(MatCopy_Basic(A, B, str));
4230 
4231   B->stencil.dim = A->stencil.dim;
4232   B->stencil.noc = A->stencil.noc;
4233   for (i = 0; i <= A->stencil.dim; i++) {
4234     B->stencil.dims[i]   = A->stencil.dims[i];
4235     B->stencil.starts[i] = A->stencil.starts[i];
4236   }
4237 
4238   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4239   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4240   PetscFunctionReturn(PETSC_SUCCESS);
4241 }
4242 
4243 /*@C
4244    MatConvert - Converts a matrix to another matrix, either of the same
4245    or different type.
4246 
4247    Collective
4248 
4249    Input Parameters:
4250 +  mat - the matrix
4251 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4252    same type as the original matrix.
4253 -  reuse - denotes if the destination matrix is to be created or reused.
4254    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
4255    `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).
4256 
4257    Output Parameter:
4258 .  M - pointer to place new matrix
4259 
4260    Level: intermediate
4261 
4262    Notes:
4263    `MatConvert()` first creates a new matrix and then copies the data from
4264    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4265    entries of one matrix to another already existing matrix context.
4266 
4267    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4268    the MPI communicator of the generated matrix is always the same as the communicator
4269    of the input matrix.
4270 
4271 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4272 @*/
4273 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4274 {
4275   PetscBool  sametype, issame, flg;
4276   PetscBool3 issymmetric, ishermitian;
4277   char       convname[256], mtype[256];
4278   Mat        B;
4279 
4280   PetscFunctionBegin;
4281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4282   PetscValidType(mat, 1);
4283   PetscValidPointer(M, 4);
4284   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4285   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4286   MatCheckPreallocated(mat, 1);
4287 
4288   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4289   if (flg) newtype = mtype;
4290 
4291   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4292   PetscCall(PetscStrcmp(newtype, "same", &issame));
4293   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4294   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");
4295 
4296   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4297     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4298     PetscFunctionReturn(PETSC_SUCCESS);
4299   }
4300 
4301   /* Cache Mat options because some converters use MatHeaderReplace  */
4302   issymmetric = mat->symmetric;
4303   ishermitian = mat->hermitian;
4304 
4305   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4306     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4307     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4308   } else {
4309     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4310     const char *prefix[3]                                 = {"seq", "mpi", ""};
4311     PetscInt    i;
4312     /*
4313        Order of precedence:
4314        0) See if newtype is a superclass of the current matrix.
4315        1) See if a specialized converter is known to the current matrix.
4316        2) See if a specialized converter is known to the desired matrix class.
4317        3) See if a good general converter is registered for the desired class
4318           (as of 6/27/03 only MATMPIADJ falls into this category).
4319        4) See if a good general converter is known for the current matrix.
4320        5) Use a really basic converter.
4321     */
4322 
4323     /* 0) See if newtype is a superclass of the current matrix.
4324           i.e mat is mpiaij and newtype is aij */
4325     for (i = 0; i < 2; i++) {
4326       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4327       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4328       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4329       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4330       if (flg) {
4331         if (reuse == MAT_INPLACE_MATRIX) {
4332           PetscCall(PetscInfo(mat, "Early return\n"));
4333           PetscFunctionReturn(PETSC_SUCCESS);
4334         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4335           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4336           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4337           PetscFunctionReturn(PETSC_SUCCESS);
4338         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4339           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4340           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4341           PetscFunctionReturn(PETSC_SUCCESS);
4342         }
4343       }
4344     }
4345     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4346     for (i = 0; i < 3; i++) {
4347       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4348       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4351       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4353       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4354       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4355       if (conv) goto foundconv;
4356     }
4357 
4358     /* 2)  See if a specialized converter is known to the desired matrix class. */
4359     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4360     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4361     PetscCall(MatSetType(B, newtype));
4362     for (i = 0; i < 3; i++) {
4363       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4367       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4368       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4369       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4370       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4371       if (conv) {
4372         PetscCall(MatDestroy(&B));
4373         goto foundconv;
4374       }
4375     }
4376 
4377     /* 3) See if a good general converter is registered for the desired class */
4378     conv = B->ops->convertfrom;
4379     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4380     PetscCall(MatDestroy(&B));
4381     if (conv) goto foundconv;
4382 
4383     /* 4) See if a good general converter is known for the current matrix */
4384     if (mat->ops->convert) conv = mat->ops->convert;
4385     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4386     if (conv) goto foundconv;
4387 
4388     /* 5) Use a really basic converter. */
4389     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4390     conv = MatConvert_Basic;
4391 
4392   foundconv:
4393     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4394     PetscCall((*conv)(mat, newtype, reuse, M));
4395     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4396       /* the block sizes must be same if the mappings are copied over */
4397       (*M)->rmap->bs = mat->rmap->bs;
4398       (*M)->cmap->bs = mat->cmap->bs;
4399       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4400       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4401       (*M)->rmap->mapping = mat->rmap->mapping;
4402       (*M)->cmap->mapping = mat->cmap->mapping;
4403     }
4404     (*M)->stencil.dim = mat->stencil.dim;
4405     (*M)->stencil.noc = mat->stencil.noc;
4406     for (i = 0; i <= mat->stencil.dim; i++) {
4407       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4408       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4409     }
4410     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4411   }
4412   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4413 
4414   /* Copy Mat options */
4415   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4416   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4417   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4418   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4419   PetscFunctionReturn(PETSC_SUCCESS);
4420 }
4421 
4422 /*@C
4423    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4424 
4425    Not Collective
4426 
4427    Input Parameter:
4428 .  mat - the matrix, must be a factored matrix
4429 
4430    Output Parameter:
4431 .   type - the string name of the package (do not free this string)
4432 
4433    Level: intermediate
4434 
4435    Fortran Note:
4436    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4437 
4438 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4439 @*/
4440 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4441 {
4442   PetscErrorCode (*conv)(Mat, MatSolverType *);
4443 
4444   PetscFunctionBegin;
4445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4446   PetscValidType(mat, 1);
4447   PetscValidPointer(type, 2);
4448   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4449   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4450   if (conv) PetscCall((*conv)(mat, type));
4451   else *type = MATSOLVERPETSC;
4452   PetscFunctionReturn(PETSC_SUCCESS);
4453 }
4454 
4455 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4456 struct _MatSolverTypeForSpecifcType {
4457   MatType mtype;
4458   /* no entry for MAT_FACTOR_NONE */
4459   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4460   MatSolverTypeForSpecifcType next;
4461 };
4462 
4463 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4464 struct _MatSolverTypeHolder {
4465   char                       *name;
4466   MatSolverTypeForSpecifcType handlers;
4467   MatSolverTypeHolder         next;
4468 };
4469 
4470 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4471 
4472 /*@C
4473    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4474 
4475    Input Parameters:
4476 +    package - name of the package, for example petsc or superlu
4477 .    mtype - the matrix type that works with this package
4478 .    ftype - the type of factorization supported by the package
4479 -    createfactor - routine that will create the factored matrix ready to be used
4480 
4481     Level: developer
4482 
4483 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4484 @*/
4485 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4486 {
4487   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4488   PetscBool                   flg;
4489   MatSolverTypeForSpecifcType inext, iprev = NULL;
4490 
4491   PetscFunctionBegin;
4492   PetscCall(MatInitializePackage());
4493   if (!next) {
4494     PetscCall(PetscNew(&MatSolverTypeHolders));
4495     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4496     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4497     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4498     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4499     PetscFunctionReturn(PETSC_SUCCESS);
4500   }
4501   while (next) {
4502     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4503     if (flg) {
4504       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4505       inext = next->handlers;
4506       while (inext) {
4507         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4508         if (flg) {
4509           inext->createfactor[(int)ftype - 1] = createfactor;
4510           PetscFunctionReturn(PETSC_SUCCESS);
4511         }
4512         iprev = inext;
4513         inext = inext->next;
4514       }
4515       PetscCall(PetscNew(&iprev->next));
4516       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4517       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4518       PetscFunctionReturn(PETSC_SUCCESS);
4519     }
4520     prev = next;
4521     next = next->next;
4522   }
4523   PetscCall(PetscNew(&prev->next));
4524   PetscCall(PetscStrallocpy(package, &prev->next->name));
4525   PetscCall(PetscNew(&prev->next->handlers));
4526   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4527   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4528   PetscFunctionReturn(PETSC_SUCCESS);
4529 }
4530 
4531 /*@C
4532    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4533 
4534    Input Parameters:
4535 +    type - name of the package, for example petsc or superlu
4536 .    ftype - the type of factorization supported by the type
4537 -    mtype - the matrix type that works with this type
4538 
4539    Output Parameters:
4540 +   foundtype - `PETSC_TRUE` if the type was registered
4541 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4542 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4543 
4544     Level: developer
4545 
4546 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4547 @*/
4548 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4549 {
4550   MatSolverTypeHolder         next = MatSolverTypeHolders;
4551   PetscBool                   flg;
4552   MatSolverTypeForSpecifcType inext;
4553 
4554   PetscFunctionBegin;
4555   if (foundtype) *foundtype = PETSC_FALSE;
4556   if (foundmtype) *foundmtype = PETSC_FALSE;
4557   if (createfactor) *createfactor = NULL;
4558 
4559   if (type) {
4560     while (next) {
4561       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4562       if (flg) {
4563         if (foundtype) *foundtype = PETSC_TRUE;
4564         inext = next->handlers;
4565         while (inext) {
4566           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4567           if (flg) {
4568             if (foundmtype) *foundmtype = PETSC_TRUE;
4569             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4570             PetscFunctionReturn(PETSC_SUCCESS);
4571           }
4572           inext = inext->next;
4573         }
4574       }
4575       next = next->next;
4576     }
4577   } else {
4578     while (next) {
4579       inext = next->handlers;
4580       while (inext) {
4581         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4582         if (flg && inext->createfactor[(int)ftype - 1]) {
4583           if (foundtype) *foundtype = PETSC_TRUE;
4584           if (foundmtype) *foundmtype = PETSC_TRUE;
4585           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4586           PetscFunctionReturn(PETSC_SUCCESS);
4587         }
4588         inext = inext->next;
4589       }
4590       next = next->next;
4591     }
4592     /* try with base classes inext->mtype */
4593     next = MatSolverTypeHolders;
4594     while (next) {
4595       inext = next->handlers;
4596       while (inext) {
4597         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4598         if (flg && inext->createfactor[(int)ftype - 1]) {
4599           if (foundtype) *foundtype = PETSC_TRUE;
4600           if (foundmtype) *foundmtype = PETSC_TRUE;
4601           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4602           PetscFunctionReturn(PETSC_SUCCESS);
4603         }
4604         inext = inext->next;
4605       }
4606       next = next->next;
4607     }
4608   }
4609   PetscFunctionReturn(PETSC_SUCCESS);
4610 }
4611 
4612 PetscErrorCode MatSolverTypeDestroy(void)
4613 {
4614   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4615   MatSolverTypeForSpecifcType inext, iprev;
4616 
4617   PetscFunctionBegin;
4618   while (next) {
4619     PetscCall(PetscFree(next->name));
4620     inext = next->handlers;
4621     while (inext) {
4622       PetscCall(PetscFree(inext->mtype));
4623       iprev = inext;
4624       inext = inext->next;
4625       PetscCall(PetscFree(iprev));
4626     }
4627     prev = next;
4628     next = next->next;
4629     PetscCall(PetscFree(prev));
4630   }
4631   MatSolverTypeHolders = NULL;
4632   PetscFunctionReturn(PETSC_SUCCESS);
4633 }
4634 
4635 /*@C
4636    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4637 
4638    Logically Collective
4639 
4640    Input Parameter:
4641 .  mat - the matrix
4642 
4643    Output Parameter:
4644 .  flg - `PETSC_TRUE` if uses the ordering
4645 
4646    Level: developer
4647 
4648    Note:
4649    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4650    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4651 
4652 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4653 @*/
4654 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4655 {
4656   PetscFunctionBegin;
4657   *flg = mat->canuseordering;
4658   PetscFunctionReturn(PETSC_SUCCESS);
4659 }
4660 
4661 /*@C
4662    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4663 
4664    Logically Collective
4665 
4666    Input Parameters:
4667 +  mat - the matrix obtained with `MatGetFactor()`
4668 -  ftype - the factorization type to be used
4669 
4670    Output Parameter:
4671 .  otype - the preferred ordering type
4672 
4673    Level: developer
4674 
4675 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4676 @*/
4677 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4678 {
4679   PetscFunctionBegin;
4680   *otype = mat->preferredordering[ftype];
4681   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4682   PetscFunctionReturn(PETSC_SUCCESS);
4683 }
4684 
4685 /*@C
4686    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4687 
4688    Collective
4689 
4690    Input Parameters:
4691 +  mat - the matrix
4692 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4693 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4694 
4695    Output Parameter:
4696 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4697 
4698    Options Database Key:
4699 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4700                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4701 
4702    Level: intermediate
4703 
4704    Notes:
4705      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4706      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4707 
4708      Users usually access the factorization solvers via `KSP`
4709 
4710       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4711      such as pastix, superlu, mumps etc.
4712 
4713       PETSc must have been ./configure to use the external solver, using the option --download-package
4714 
4715       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4716       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4717       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4718 
4719    Developer Note:
4720       This should actually be called `MatCreateFactor()` since it creates a new factor object
4721 
4722 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4723           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4724 @*/
4725 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4726 {
4727   PetscBool foundtype, foundmtype;
4728   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4729 
4730   PetscFunctionBegin;
4731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4732   PetscValidType(mat, 1);
4733 
4734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4735   MatCheckPreallocated(mat, 1);
4736 
4737   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4738   if (!foundtype) {
4739     if (type) {
4740       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],
4741               ((PetscObject)mat)->type_name, type);
4742     } else {
4743       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);
4744     }
4745   }
4746   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4747   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);
4748 
4749   PetscCall((*conv)(mat, ftype, f));
4750   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4751   PetscFunctionReturn(PETSC_SUCCESS);
4752 }
4753 
4754 /*@C
4755    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4756 
4757    Not Collective
4758 
4759    Input Parameters:
4760 +  mat - the matrix
4761 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4762 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4763 
4764    Output Parameter:
4765 .    flg - PETSC_TRUE if the factorization is available
4766 
4767    Level: intermediate
4768 
4769    Notes:
4770       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4771      such as pastix, superlu, mumps etc.
4772 
4773       PETSc must have been ./configure to use the external solver, using the option --download-package
4774 
4775    Developer Note:
4776       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4777 
4778 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4779           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4780 @*/
4781 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4782 {
4783   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4784 
4785   PetscFunctionBegin;
4786   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4787   PetscValidType(mat, 1);
4788   PetscValidBoolPointer(flg, 4);
4789 
4790   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4791   MatCheckPreallocated(mat, 1);
4792 
4793   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4794   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4795   PetscFunctionReturn(PETSC_SUCCESS);
4796 }
4797 
4798 /*@
4799    MatDuplicate - Duplicates a matrix including the non-zero structure.
4800 
4801    Collective
4802 
4803    Input Parameters:
4804 +  mat - the matrix
4805 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4806         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4807 
4808    Output Parameter:
4809 .  M - pointer to place new matrix
4810 
4811    Level: intermediate
4812 
4813    Notes:
4814     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4815 
4816     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.
4817 
4818     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
4819     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4820     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4821 
4822 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4823 @*/
4824 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4825 {
4826   Mat         B;
4827   VecType     vtype;
4828   PetscInt    i;
4829   PetscObject dm;
4830   void (*viewf)(void);
4831 
4832   PetscFunctionBegin;
4833   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4834   PetscValidType(mat, 1);
4835   PetscValidPointer(M, 3);
4836   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4837   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4838   MatCheckPreallocated(mat, 1);
4839 
4840   *M = NULL;
4841   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4842   PetscUseTypeMethod(mat, duplicate, op, M);
4843   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4844   B = *M;
4845 
4846   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4847   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4848   PetscCall(MatGetVecType(mat, &vtype));
4849   PetscCall(MatSetVecType(B, vtype));
4850 
4851   B->stencil.dim = mat->stencil.dim;
4852   B->stencil.noc = mat->stencil.noc;
4853   for (i = 0; i <= mat->stencil.dim; i++) {
4854     B->stencil.dims[i]   = mat->stencil.dims[i];
4855     B->stencil.starts[i] = mat->stencil.starts[i];
4856   }
4857 
4858   B->nooffproczerorows = mat->nooffproczerorows;
4859   B->nooffprocentries  = mat->nooffprocentries;
4860 
4861   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4862   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4863   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4864   PetscFunctionReturn(PETSC_SUCCESS);
4865 }
4866 
4867 /*@
4868    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4869 
4870    Logically Collective
4871 
4872    Input Parameter:
4873 .  mat - the matrix
4874 
4875    Output Parameter:
4876 .  v - the diagonal of the matrix
4877 
4878    Level: intermediate
4879 
4880    Note:
4881    Currently only correct in parallel for square matrices.
4882 
4883 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4884 @*/
4885 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4886 {
4887   PetscFunctionBegin;
4888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4889   PetscValidType(mat, 1);
4890   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4891   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4892   MatCheckPreallocated(mat, 1);
4893 
4894   PetscUseTypeMethod(mat, getdiagonal, v);
4895   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4896   PetscFunctionReturn(PETSC_SUCCESS);
4897 }
4898 
4899 /*@C
4900    MatGetRowMin - Gets the minimum value (of the real part) of each
4901         row of the matrix
4902 
4903    Logically Collective
4904 
4905    Input Parameter:
4906 .  mat - the matrix
4907 
4908    Output Parameters:
4909 +  v - the vector for storing the maximums
4910 -  idx - the indices of the column found for each row (optional)
4911 
4912    Level: intermediate
4913 
4914    Note:
4915     The result of this call are the same as if one converted the matrix to dense format
4916       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4917 
4918     This code is only implemented for a couple of matrix formats.
4919 
4920 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4921           `MatGetRowMax()`
4922 @*/
4923 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4924 {
4925   PetscFunctionBegin;
4926   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4927   PetscValidType(mat, 1);
4928   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4929   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4930 
4931   if (!mat->cmap->N) {
4932     PetscCall(VecSet(v, PETSC_MAX_REAL));
4933     if (idx) {
4934       PetscInt i, m = mat->rmap->n;
4935       for (i = 0; i < m; i++) idx[i] = -1;
4936     }
4937   } else {
4938     MatCheckPreallocated(mat, 1);
4939   }
4940   PetscUseTypeMethod(mat, getrowmin, v, idx);
4941   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4942   PetscFunctionReturn(PETSC_SUCCESS);
4943 }
4944 
4945 /*@C
4946    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4947         row of the matrix
4948 
4949    Logically Collective
4950 
4951    Input Parameter:
4952 .  mat - the matrix
4953 
4954    Output Parameters:
4955 +  v - the vector for storing the minimums
4956 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4957 
4958    Level: intermediate
4959 
4960    Notes:
4961     if a row is completely empty or has only 0.0 values then the idx[] value for that
4962     row is 0 (the first column).
4963 
4964     This code is only implemented for a couple of matrix formats.
4965 
4966 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4967 @*/
4968 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4969 {
4970   PetscFunctionBegin;
4971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4972   PetscValidType(mat, 1);
4973   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4974   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4975   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4976 
4977   if (!mat->cmap->N) {
4978     PetscCall(VecSet(v, 0.0));
4979     if (idx) {
4980       PetscInt i, m = mat->rmap->n;
4981       for (i = 0; i < m; i++) idx[i] = -1;
4982     }
4983   } else {
4984     MatCheckPreallocated(mat, 1);
4985     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4986     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4987   }
4988   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4989   PetscFunctionReturn(PETSC_SUCCESS);
4990 }
4991 
4992 /*@C
4993    MatGetRowMax - Gets the maximum value (of the real part) of each
4994         row of the matrix
4995 
4996    Logically Collective
4997 
4998    Input Parameter:
4999 .  mat - the matrix
5000 
5001    Output Parameters:
5002 +  v - the vector for storing the maximums
5003 -  idx - the indices of the column found for each row (optional)
5004 
5005    Level: intermediate
5006 
5007    Notes:
5008     The result of this call are the same as if one converted the matrix to dense format
5009       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5010 
5011     This code is only implemented for a couple of matrix formats.
5012 
5013 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5014 @*/
5015 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5016 {
5017   PetscFunctionBegin;
5018   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5019   PetscValidType(mat, 1);
5020   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5021   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5022 
5023   if (!mat->cmap->N) {
5024     PetscCall(VecSet(v, PETSC_MIN_REAL));
5025     if (idx) {
5026       PetscInt i, m = mat->rmap->n;
5027       for (i = 0; i < m; i++) idx[i] = -1;
5028     }
5029   } else {
5030     MatCheckPreallocated(mat, 1);
5031     PetscUseTypeMethod(mat, getrowmax, v, idx);
5032   }
5033   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5034   PetscFunctionReturn(PETSC_SUCCESS);
5035 }
5036 
5037 /*@C
5038    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5039         row of the matrix
5040 
5041    Logically Collective
5042 
5043    Input Parameter:
5044 .  mat - the matrix
5045 
5046    Output Parameters:
5047 +  v - the vector for storing the maximums
5048 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5049 
5050    Level: intermediate
5051 
5052    Notes:
5053     if a row is completely empty or has only 0.0 values then the idx[] value for that
5054     row is 0 (the first column).
5055 
5056     This code is only implemented for a couple of matrix formats.
5057 
5058 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5059 @*/
5060 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5061 {
5062   PetscFunctionBegin;
5063   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5064   PetscValidType(mat, 1);
5065   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5067 
5068   if (!mat->cmap->N) {
5069     PetscCall(VecSet(v, 0.0));
5070     if (idx) {
5071       PetscInt i, m = mat->rmap->n;
5072       for (i = 0; i < m; i++) idx[i] = -1;
5073     }
5074   } else {
5075     MatCheckPreallocated(mat, 1);
5076     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5077     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5078   }
5079   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5080   PetscFunctionReturn(PETSC_SUCCESS);
5081 }
5082 
5083 /*@
5084    MatGetRowSum - Gets the sum of each row of the matrix
5085 
5086    Logically or Neighborhood Collective
5087 
5088    Input Parameter:
5089 .  mat - the matrix
5090 
5091    Output Parameter:
5092 .  v - the vector for storing the sum of rows
5093 
5094    Level: intermediate
5095 
5096    Notes:
5097     This code is slow since it is not currently specialized for different formats
5098 
5099 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5100 @*/
5101 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5102 {
5103   Vec ones;
5104 
5105   PetscFunctionBegin;
5106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5107   PetscValidType(mat, 1);
5108   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5109   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5110   MatCheckPreallocated(mat, 1);
5111   PetscCall(MatCreateVecs(mat, &ones, NULL));
5112   PetscCall(VecSet(ones, 1.));
5113   PetscCall(MatMult(mat, ones, v));
5114   PetscCall(VecDestroy(&ones));
5115   PetscFunctionReturn(PETSC_SUCCESS);
5116 }
5117 
5118 /*@
5119    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5120    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5121 
5122    Collective
5123 
5124    Input Parameter:
5125 .  mat - the matrix to provide the transpose
5126 
5127    Output Parameter:
5128 .  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
5129 
5130    Level: advanced
5131 
5132    Note:
5133    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
5134    routine allows bypassing that call.
5135 
5136 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5137 @*/
5138 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5139 {
5140   PetscContainer  rB = NULL;
5141   MatParentState *rb = NULL;
5142 
5143   PetscFunctionBegin;
5144   PetscCall(PetscNew(&rb));
5145   rb->id    = ((PetscObject)mat)->id;
5146   rb->state = 0;
5147   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5148   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5149   PetscCall(PetscContainerSetPointer(rB, rb));
5150   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5151   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5152   PetscCall(PetscObjectDereference((PetscObject)rB));
5153   PetscFunctionReturn(PETSC_SUCCESS);
5154 }
5155 
5156 /*@
5157    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5158 
5159    Collective
5160 
5161    Input Parameters:
5162 +  mat - the matrix to transpose
5163 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5164 
5165    Output Parameter:
5166 .  B - the transpose
5167 
5168    Level: intermediate
5169 
5170    Notes:
5171      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5172 
5173      `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
5174      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5175 
5176      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.
5177 
5178      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5179 
5180      If mat is unchanged from the last call this function returns immediately without recomputing the result
5181 
5182      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5183 
5184 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5185           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5186 @*/
5187 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5188 {
5189   PetscContainer  rB = NULL;
5190   MatParentState *rb = NULL;
5191 
5192   PetscFunctionBegin;
5193   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5194   PetscValidType(mat, 1);
5195   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5196   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5197   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5198   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5199   MatCheckPreallocated(mat, 1);
5200   if (reuse == MAT_REUSE_MATRIX) {
5201     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5202     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5203     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5204     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5205     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5206   }
5207 
5208   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5209   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5210     PetscUseTypeMethod(mat, transpose, reuse, B);
5211     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5212   }
5213   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5214 
5215   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5216   if (reuse != MAT_INPLACE_MATRIX) {
5217     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5218     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5219     rb->state        = ((PetscObject)mat)->state;
5220     rb->nonzerostate = mat->nonzerostate;
5221   }
5222   PetscFunctionReturn(PETSC_SUCCESS);
5223 }
5224 
5225 /*@
5226    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5227 
5228    Collective
5229 
5230    Input Parameter:
5231 .  A - the matrix to transpose
5232 
5233    Output Parameter:
5234 .  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
5235       numerical portion.
5236 
5237    Level: intermediate
5238 
5239    Note:
5240    This is not supported for many matrix types, use `MatTranspose()` in those cases
5241 
5242 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5243 @*/
5244 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5245 {
5246   PetscFunctionBegin;
5247   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5248   PetscValidType(A, 1);
5249   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5250   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5251   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5252   PetscUseTypeMethod(A, transposesymbolic, B);
5253   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5254 
5255   PetscCall(MatTransposeSetPrecursor(A, *B));
5256   PetscFunctionReturn(PETSC_SUCCESS);
5257 }
5258 
5259 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5260 {
5261   PetscContainer  rB;
5262   MatParentState *rb;
5263 
5264   PetscFunctionBegin;
5265   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5266   PetscValidType(A, 1);
5267   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5268   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5269   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5270   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5271   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5272   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5273   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5274   PetscFunctionReturn(PETSC_SUCCESS);
5275 }
5276 
5277 /*@
5278    MatIsTranspose - Test whether a matrix is another one's transpose,
5279         or its own, in which case it tests symmetry.
5280 
5281    Collective
5282 
5283    Input Parameters:
5284 +  A - the matrix to test
5285 .  B - the matrix to test against, this can equal the first parameter
5286 -  tol - tolerance, differences between entries smaller than this are counted as zero
5287 
5288    Output Parameter:
5289 .  flg - the result
5290 
5291    Level: intermediate
5292 
5293    Notes:
5294    Only available for `MATAIJ` matrices.
5295 
5296    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5297    test involves parallel copies of the block-offdiagonal parts of the matrix.
5298 
5299 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5300 @*/
5301 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5302 {
5303   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5304 
5305   PetscFunctionBegin;
5306   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5307   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5308   PetscValidBoolPointer(flg, 4);
5309   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5310   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5311   *flg = PETSC_FALSE;
5312   if (f && g) {
5313     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5314     PetscCall((*f)(A, B, tol, flg));
5315   } else {
5316     MatType mattype;
5317 
5318     PetscCall(MatGetType(f ? B : A, &mattype));
5319     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5320   }
5321   PetscFunctionReturn(PETSC_SUCCESS);
5322 }
5323 
5324 /*@
5325    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5326 
5327    Collective
5328 
5329    Input Parameters:
5330 +  mat - the matrix to transpose and complex conjugate
5331 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5332 
5333    Output Parameter:
5334 .  B - the Hermitian transpose
5335 
5336    Level: intermediate
5337 
5338 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5339 @*/
5340 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5341 {
5342   PetscFunctionBegin;
5343   PetscCall(MatTranspose(mat, reuse, B));
5344 #if defined(PETSC_USE_COMPLEX)
5345   PetscCall(MatConjugate(*B));
5346 #endif
5347   PetscFunctionReturn(PETSC_SUCCESS);
5348 }
5349 
5350 /*@
5351    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5352 
5353    Collective
5354 
5355    Input Parameters:
5356 +  A - the matrix to test
5357 .  B - the matrix to test against, this can equal the first parameter
5358 -  tol - tolerance, differences between entries smaller than this are counted as zero
5359 
5360    Output Parameter:
5361 .  flg - the result
5362 
5363    Level: intermediate
5364 
5365    Notes:
5366    Only available for `MATAIJ` matrices.
5367 
5368    The sequential algorithm
5369    has a running time of the order of the number of nonzeros; the parallel
5370    test involves parallel copies of the block-offdiagonal parts of the matrix.
5371 
5372 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5373 @*/
5374 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5375 {
5376   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5377 
5378   PetscFunctionBegin;
5379   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5380   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5381   PetscValidBoolPointer(flg, 4);
5382   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5383   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5384   if (f && g) {
5385     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5386     PetscCall((*f)(A, B, tol, flg));
5387   }
5388   PetscFunctionReturn(PETSC_SUCCESS);
5389 }
5390 
5391 /*@
5392    MatPermute - Creates a new matrix with rows and columns permuted from the
5393    original.
5394 
5395    Collective
5396 
5397    Input Parameters:
5398 +  mat - the matrix to permute
5399 .  row - row permutation, each processor supplies only the permutation for its rows
5400 -  col - column permutation, each processor supplies only the permutation for its columns
5401 
5402    Output Parameter:
5403 .  B - the permuted matrix
5404 
5405    Level: advanced
5406 
5407    Note:
5408    The index sets map from row/col of permuted matrix to row/col of original matrix.
5409    The index sets should be on the same communicator as mat and have the same local sizes.
5410 
5411    Developer Note:
5412      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5413      exploit the fact that row and col are permutations, consider implementing the
5414      more general `MatCreateSubMatrix()` instead.
5415 
5416 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5417 @*/
5418 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5419 {
5420   PetscFunctionBegin;
5421   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5422   PetscValidType(mat, 1);
5423   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5424   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5425   PetscValidPointer(B, 4);
5426   PetscCheckSameComm(mat, 1, row, 2);
5427   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5428   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5429   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5430   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5431   MatCheckPreallocated(mat, 1);
5432 
5433   if (mat->ops->permute) {
5434     PetscUseTypeMethod(mat, permute, row, col, B);
5435     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5436   } else {
5437     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5438   }
5439   PetscFunctionReturn(PETSC_SUCCESS);
5440 }
5441 
5442 /*@
5443    MatEqual - Compares two matrices.
5444 
5445    Collective
5446 
5447    Input Parameters:
5448 +  A - the first matrix
5449 -  B - the second matrix
5450 
5451    Output Parameter:
5452 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5453 
5454    Level: intermediate
5455 
5456 .seealso: [](chapter_matrices), `Mat`
5457 @*/
5458 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5459 {
5460   PetscFunctionBegin;
5461   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5462   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5463   PetscValidType(A, 1);
5464   PetscValidType(B, 2);
5465   PetscValidBoolPointer(flg, 3);
5466   PetscCheckSameComm(A, 1, B, 2);
5467   MatCheckPreallocated(A, 1);
5468   MatCheckPreallocated(B, 2);
5469   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5470   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5471   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,
5472              B->cmap->N);
5473   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5474     PetscUseTypeMethod(A, equal, B, flg);
5475   } else {
5476     PetscCall(MatMultEqual(A, B, 10, flg));
5477   }
5478   PetscFunctionReturn(PETSC_SUCCESS);
5479 }
5480 
5481 /*@
5482    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5483    matrices that are stored as vectors.  Either of the two scaling
5484    matrices can be `NULL`.
5485 
5486    Collective
5487 
5488    Input Parameters:
5489 +  mat - the matrix to be scaled
5490 .  l - the left scaling vector (or `NULL`)
5491 -  r - the right scaling vector (or `NULL`)
5492 
5493    Level: intermediate
5494 
5495    Note:
5496    `MatDiagonalScale()` computes A = LAR, where
5497    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5498    The L scales the rows of the matrix, the R scales the columns of the matrix.
5499 
5500 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5501 @*/
5502 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5503 {
5504   PetscFunctionBegin;
5505   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5506   PetscValidType(mat, 1);
5507   if (l) {
5508     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5509     PetscCheckSameComm(mat, 1, l, 2);
5510   }
5511   if (r) {
5512     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5513     PetscCheckSameComm(mat, 1, r, 3);
5514   }
5515   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5516   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5517   MatCheckPreallocated(mat, 1);
5518   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5519 
5520   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5521   PetscUseTypeMethod(mat, diagonalscale, l, r);
5522   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5523   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5524   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5525   PetscFunctionReturn(PETSC_SUCCESS);
5526 }
5527 
5528 /*@
5529     MatScale - Scales all elements of a matrix by a given number.
5530 
5531     Logically Collective
5532 
5533     Input Parameters:
5534 +   mat - the matrix to be scaled
5535 -   a  - the scaling value
5536 
5537     Level: intermediate
5538 
5539 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5540 @*/
5541 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5542 {
5543   PetscFunctionBegin;
5544   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5545   PetscValidType(mat, 1);
5546   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5547   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5548   PetscValidLogicalCollectiveScalar(mat, a, 2);
5549   MatCheckPreallocated(mat, 1);
5550 
5551   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5552   if (a != (PetscScalar)1.0) {
5553     PetscUseTypeMethod(mat, scale, a);
5554     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5555   }
5556   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5557   PetscFunctionReturn(PETSC_SUCCESS);
5558 }
5559 
5560 /*@
5561    MatNorm - Calculates various norms of a matrix.
5562 
5563    Collective
5564 
5565    Input Parameters:
5566 +  mat - the matrix
5567 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5568 
5569    Output Parameter:
5570 .  nrm - the resulting norm
5571 
5572    Level: intermediate
5573 
5574 .seealso: [](chapter_matrices), `Mat`
5575 @*/
5576 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5577 {
5578   PetscFunctionBegin;
5579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5580   PetscValidType(mat, 1);
5581   PetscValidRealPointer(nrm, 3);
5582 
5583   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5584   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5585   MatCheckPreallocated(mat, 1);
5586 
5587   PetscUseTypeMethod(mat, norm, type, nrm);
5588   PetscFunctionReturn(PETSC_SUCCESS);
5589 }
5590 
5591 /*
5592      This variable is used to prevent counting of MatAssemblyBegin() that
5593    are called from within a MatAssemblyEnd().
5594 */
5595 static PetscInt MatAssemblyEnd_InUse = 0;
5596 /*@
5597    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5598    be called after completing all calls to `MatSetValues()`.
5599 
5600    Collective
5601 
5602    Input Parameters:
5603 +  mat - the matrix
5604 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5605 
5606    Level: beginner
5607 
5608    Notes:
5609    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5610    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5611 
5612    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5613    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5614    using the matrix.
5615 
5616    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5617    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
5618    a global collective operation requiring all processes that share the matrix.
5619 
5620    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5621    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5622    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5623 
5624 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5625 @*/
5626 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5627 {
5628   PetscFunctionBegin;
5629   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5630   PetscValidType(mat, 1);
5631   MatCheckPreallocated(mat, 1);
5632   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5633   if (mat->assembled) {
5634     mat->was_assembled = PETSC_TRUE;
5635     mat->assembled     = PETSC_FALSE;
5636   }
5637 
5638   if (!MatAssemblyEnd_InUse) {
5639     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5640     PetscTryTypeMethod(mat, assemblybegin, type);
5641     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5642   } else PetscTryTypeMethod(mat, assemblybegin, type);
5643   PetscFunctionReturn(PETSC_SUCCESS);
5644 }
5645 
5646 /*@
5647    MatAssembled - Indicates if a matrix has been assembled and is ready for
5648      use; for example, in matrix-vector product.
5649 
5650    Not Collective
5651 
5652    Input Parameter:
5653 .  mat - the matrix
5654 
5655    Output Parameter:
5656 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5657 
5658    Level: advanced
5659 
5660 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5661 @*/
5662 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5663 {
5664   PetscFunctionBegin;
5665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5666   PetscValidBoolPointer(assembled, 2);
5667   *assembled = mat->assembled;
5668   PetscFunctionReturn(PETSC_SUCCESS);
5669 }
5670 
5671 /*@
5672    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5673    be called after `MatAssemblyBegin()`.
5674 
5675    Collective
5676 
5677    Input Parameters:
5678 +  mat - the matrix
5679 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5680 
5681    Options Database Keys:
5682 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5683 .  -mat_view ::ascii_info_detail - Prints more detailed info
5684 .  -mat_view - Prints matrix in ASCII format
5685 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5686 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5687 .  -display <name> - Sets display name (default is host)
5688 .  -draw_pause <sec> - Sets number of seconds to pause after display
5689 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5690 .  -viewer_socket_machine <machine> - Machine to use for socket
5691 .  -viewer_socket_port <port> - Port number to use for socket
5692 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5693 
5694    Level: beginner
5695 
5696 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5697 @*/
5698 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5699 {
5700   static PetscInt inassm = 0;
5701   PetscBool       flg    = PETSC_FALSE;
5702 
5703   PetscFunctionBegin;
5704   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5705   PetscValidType(mat, 1);
5706 
5707   inassm++;
5708   MatAssemblyEnd_InUse++;
5709   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5710     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5711     PetscTryTypeMethod(mat, assemblyend, type);
5712     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5713   } else PetscTryTypeMethod(mat, assemblyend, type);
5714 
5715   /* Flush assembly is not a true assembly */
5716   if (type != MAT_FLUSH_ASSEMBLY) {
5717     if (mat->num_ass) {
5718       if (!mat->symmetry_eternal) {
5719         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5720         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5721       }
5722       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5723       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5724     }
5725     mat->num_ass++;
5726     mat->assembled        = PETSC_TRUE;
5727     mat->ass_nonzerostate = mat->nonzerostate;
5728   }
5729 
5730   mat->insertmode = NOT_SET_VALUES;
5731   MatAssemblyEnd_InUse--;
5732   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5733   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5734     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5735 
5736     if (mat->checksymmetryonassembly) {
5737       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5738       if (flg) {
5739         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5740       } else {
5741         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5742       }
5743     }
5744     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5745   }
5746   inassm--;
5747   PetscFunctionReturn(PETSC_SUCCESS);
5748 }
5749 
5750 /*@
5751    MatSetOption - Sets a parameter option for a matrix. Some options
5752    may be specific to certain storage formats.  Some options
5753    determine how values will be inserted (or added). Sorted,
5754    row-oriented input will generally assemble the fastest. The default
5755    is row-oriented.
5756 
5757    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5758 
5759    Input Parameters:
5760 +  mat - the matrix
5761 .  option - the option, one of those listed below (and possibly others),
5762 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5763 
5764   Options Describing Matrix Structure:
5765 +    `MAT_SPD` - symmetric positive definite
5766 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5767 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5768 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5769 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5770 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5771 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5772 
5773    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5774    do not need to be computed (usually at a high cost)
5775 
5776    Options For Use with `MatSetValues()`:
5777    Insert a logically dense subblock, which can be
5778 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5779 
5780    These options reflect the data you pass in with `MatSetValues()`; it has
5781    nothing to do with how the data is stored internally in the matrix
5782    data structure.
5783 
5784    When (re)assembling a matrix, we can restrict the input for
5785    efficiency/debugging purposes.  These options include
5786 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5787 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5788 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5789 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5790 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5791 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5792         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5793         performance for very large process counts.
5794 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5795         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5796         functions, instead sending only neighbor messages.
5797 
5798    Level: intermediate
5799 
5800    Notes:
5801    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5802 
5803    Some options are relevant only for particular matrix types and
5804    are thus ignored by others.  Other options are not supported by
5805    certain matrix types and will generate an error message if set.
5806 
5807    If using Fortran to compute a matrix, one may need to
5808    use the column-oriented option (or convert to the row-oriented
5809    format).
5810 
5811    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5812    that would generate a new entry in the nonzero structure is instead
5813    ignored.  Thus, if memory has not already been allocated for this particular
5814    data, then the insertion is ignored. For dense matrices, in which
5815    the entire array is allocated, no entries are ever ignored.
5816    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5817 
5818    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5819    that would generate a new entry in the nonzero structure instead produces
5820    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
5821 
5822    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5823    that would generate a new entry that has not been preallocated will
5824    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5825    only.) This is a useful flag when debugging matrix memory preallocation.
5826    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5827 
5828    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5829    other processors should be dropped, rather than stashed.
5830    This is useful if you know that the "owning" processor is also
5831    always generating the correct matrix entries, so that PETSc need
5832    not transfer duplicate entries generated on another processor.
5833 
5834    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5835    searches during matrix assembly. When this flag is set, the hash table
5836    is created during the first matrix assembly. This hash table is
5837    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5838    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5839    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5840    supported by `MATMPIBAIJ` format only.
5841 
5842    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5843    are kept in the nonzero structure
5844 
5845    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5846    a zero location in the matrix
5847 
5848    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5849 
5850    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5851         zero row routines and thus improves performance for very large process counts.
5852 
5853    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5854         part of the matrix (since they should match the upper triangular part).
5855 
5856    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5857                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5858                      with finite difference schemes with non-periodic boundary conditions.
5859 
5860    Developer Note:
5861    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5862    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5863    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5864    not changed.
5865 
5866 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5867 @*/
5868 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5869 {
5870   PetscFunctionBegin;
5871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5872   if (op > 0) {
5873     PetscValidLogicalCollectiveEnum(mat, op, 2);
5874     PetscValidLogicalCollectiveBool(mat, flg, 3);
5875   }
5876 
5877   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);
5878 
5879   switch (op) {
5880   case MAT_FORCE_DIAGONAL_ENTRIES:
5881     mat->force_diagonals = flg;
5882     PetscFunctionReturn(PETSC_SUCCESS);
5883   case MAT_NO_OFF_PROC_ENTRIES:
5884     mat->nooffprocentries = flg;
5885     PetscFunctionReturn(PETSC_SUCCESS);
5886   case MAT_SUBSET_OFF_PROC_ENTRIES:
5887     mat->assembly_subset = flg;
5888     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5889 #if !defined(PETSC_HAVE_MPIUNI)
5890       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5891 #endif
5892       mat->stash.first_assembly_done = PETSC_FALSE;
5893     }
5894     PetscFunctionReturn(PETSC_SUCCESS);
5895   case MAT_NO_OFF_PROC_ZERO_ROWS:
5896     mat->nooffproczerorows = flg;
5897     PetscFunctionReturn(PETSC_SUCCESS);
5898   case MAT_SPD:
5899     if (flg) {
5900       mat->spd                    = PETSC_BOOL3_TRUE;
5901       mat->symmetric              = PETSC_BOOL3_TRUE;
5902       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5903     } else {
5904       mat->spd = PETSC_BOOL3_FALSE;
5905     }
5906     break;
5907   case MAT_SYMMETRIC:
5908     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5909     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5910 #if !defined(PETSC_USE_COMPLEX)
5911     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5912 #endif
5913     break;
5914   case MAT_HERMITIAN:
5915     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5916     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5917 #if !defined(PETSC_USE_COMPLEX)
5918     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5919 #endif
5920     break;
5921   case MAT_STRUCTURALLY_SYMMETRIC:
5922     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5923     break;
5924   case MAT_SYMMETRY_ETERNAL:
5925     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");
5926     mat->symmetry_eternal = flg;
5927     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5928     break;
5929   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5930     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");
5931     mat->structural_symmetry_eternal = flg;
5932     break;
5933   case MAT_SPD_ETERNAL:
5934     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");
5935     mat->spd_eternal = flg;
5936     if (flg) {
5937       mat->structural_symmetry_eternal = PETSC_TRUE;
5938       mat->symmetry_eternal            = PETSC_TRUE;
5939     }
5940     break;
5941   case MAT_STRUCTURE_ONLY:
5942     mat->structure_only = flg;
5943     break;
5944   case MAT_SORTED_FULL:
5945     mat->sortedfull = flg;
5946     break;
5947   default:
5948     break;
5949   }
5950   PetscTryTypeMethod(mat, setoption, op, flg);
5951   PetscFunctionReturn(PETSC_SUCCESS);
5952 }
5953 
5954 /*@
5955    MatGetOption - Gets a parameter option that has been set for a matrix.
5956 
5957    Logically Collective
5958 
5959    Input Parameters:
5960 +  mat - the matrix
5961 -  option - the option, this only responds to certain options, check the code for which ones
5962 
5963    Output Parameter:
5964 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5965 
5966    Level: intermediate
5967 
5968     Notes:
5969     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5970 
5971     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5972     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5973 
5974 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5975     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5976 @*/
5977 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5978 {
5979   PetscFunctionBegin;
5980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5981   PetscValidType(mat, 1);
5982 
5983   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);
5984   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()");
5985 
5986   switch (op) {
5987   case MAT_NO_OFF_PROC_ENTRIES:
5988     *flg = mat->nooffprocentries;
5989     break;
5990   case MAT_NO_OFF_PROC_ZERO_ROWS:
5991     *flg = mat->nooffproczerorows;
5992     break;
5993   case MAT_SYMMETRIC:
5994     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5995     break;
5996   case MAT_HERMITIAN:
5997     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5998     break;
5999   case MAT_STRUCTURALLY_SYMMETRIC:
6000     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6001     break;
6002   case MAT_SPD:
6003     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6004     break;
6005   case MAT_SYMMETRY_ETERNAL:
6006     *flg = mat->symmetry_eternal;
6007     break;
6008   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6009     *flg = mat->symmetry_eternal;
6010     break;
6011   default:
6012     break;
6013   }
6014   PetscFunctionReturn(PETSC_SUCCESS);
6015 }
6016 
6017 /*@
6018    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6019    this routine retains the old nonzero structure.
6020 
6021    Logically Collective
6022 
6023    Input Parameter:
6024 .  mat - the matrix
6025 
6026    Level: intermediate
6027 
6028    Note:
6029     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.
6030    See the Performance chapter of the users manual for information on preallocating matrices.
6031 
6032 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6033 @*/
6034 PetscErrorCode MatZeroEntries(Mat mat)
6035 {
6036   PetscFunctionBegin;
6037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6038   PetscValidType(mat, 1);
6039   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6040   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");
6041   MatCheckPreallocated(mat, 1);
6042 
6043   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6044   PetscUseTypeMethod(mat, zeroentries);
6045   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6046   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6047   PetscFunctionReturn(PETSC_SUCCESS);
6048 }
6049 
6050 /*@
6051    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6052    of a set of rows and columns of a matrix.
6053 
6054    Collective
6055 
6056    Input Parameters:
6057 +  mat - the matrix
6058 .  numRows - the number of rows/columns to zero
6059 .  rows - the global row indices
6060 .  diag - value put in the diagonal of the eliminated rows
6061 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6062 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6063 
6064    Level: intermediate
6065 
6066    Notes:
6067    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6068 
6069    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6070    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
6071 
6072    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6073    Krylov method to take advantage of the known solution on the zeroed rows.
6074 
6075    For the parallel case, all processes that share the matrix (i.e.,
6076    those in the communicator used for matrix creation) MUST call this
6077    routine, regardless of whether any rows being zeroed are owned by
6078    them.
6079 
6080    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6081 
6082    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6083    list only rows local to itself).
6084 
6085    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6086 
6087 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6088           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6089 @*/
6090 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6091 {
6092   PetscFunctionBegin;
6093   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6094   PetscValidType(mat, 1);
6095   if (numRows) PetscValidIntPointer(rows, 3);
6096   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6097   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6098   MatCheckPreallocated(mat, 1);
6099 
6100   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6101   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6102   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6103   PetscFunctionReturn(PETSC_SUCCESS);
6104 }
6105 
6106 /*@
6107    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6108    of a set of rows and columns of a matrix.
6109 
6110    Collective
6111 
6112    Input Parameters:
6113 +  mat - the matrix
6114 .  is - the rows to zero
6115 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6116 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6117 -  b - optional vector of right hand side, that will be adjusted by provided solution
6118 
6119    Level: intermediate
6120 
6121    Note:
6122    See `MatZeroRowsColumns()` for details on how this routine operates.
6123 
6124 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6125           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6126 @*/
6127 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6128 {
6129   PetscInt        numRows;
6130   const PetscInt *rows;
6131 
6132   PetscFunctionBegin;
6133   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6134   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6135   PetscValidType(mat, 1);
6136   PetscValidType(is, 2);
6137   PetscCall(ISGetLocalSize(is, &numRows));
6138   PetscCall(ISGetIndices(is, &rows));
6139   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6140   PetscCall(ISRestoreIndices(is, &rows));
6141   PetscFunctionReturn(PETSC_SUCCESS);
6142 }
6143 
6144 /*@
6145    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6146    of a set of rows of a matrix.
6147 
6148    Collective
6149 
6150    Input Parameters:
6151 +  mat - the matrix
6152 .  numRows - the number of rows to zero
6153 .  rows - the global row indices
6154 .  diag - value put in the diagonal of the zeroed rows
6155 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6156 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6157 
6158    Level: intermediate
6159 
6160    Notes:
6161    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6162 
6163    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6164 
6165    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6166    Krylov method to take advantage of the known solution on the zeroed rows.
6167 
6168    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)
6169    from the matrix.
6170 
6171    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6172    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
6173    formats this does not alter the nonzero structure.
6174 
6175    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6176    of the matrix is not changed the values are
6177    merely zeroed.
6178 
6179    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6180    formats can optionally remove the main diagonal entry from the
6181    nonzero structure as well, by passing 0.0 as the final argument).
6182 
6183    For the parallel case, all processes that share the matrix (i.e.,
6184    those in the communicator used for matrix creation) MUST call this
6185    routine, regardless of whether any rows being zeroed are owned by
6186    them.
6187 
6188    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6189    list only rows local to itself).
6190 
6191    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6192    owns that are to be zeroed. This saves a global synchronization in the implementation.
6193 
6194 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6195           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6196 @*/
6197 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6198 {
6199   PetscFunctionBegin;
6200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6201   PetscValidType(mat, 1);
6202   if (numRows) PetscValidIntPointer(rows, 3);
6203   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6204   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6205   MatCheckPreallocated(mat, 1);
6206 
6207   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6208   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6209   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6210   PetscFunctionReturn(PETSC_SUCCESS);
6211 }
6212 
6213 /*@
6214    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6215    of a set of rows of a matrix.
6216 
6217    Collective
6218 
6219    Input Parameters:
6220 +  mat - the matrix
6221 .  is - index set of rows to remove (if `NULL` then no row is removed)
6222 .  diag - value put in all diagonals of eliminated rows
6223 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6224 -  b - optional vector of right hand side, that will be adjusted by provided solution
6225 
6226    Level: intermediate
6227 
6228    Note:
6229    See `MatZeroRows()` for details on how this routine operates.
6230 
6231 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6232           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6233 @*/
6234 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6235 {
6236   PetscInt        numRows = 0;
6237   const PetscInt *rows    = NULL;
6238 
6239   PetscFunctionBegin;
6240   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6241   PetscValidType(mat, 1);
6242   if (is) {
6243     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6244     PetscCall(ISGetLocalSize(is, &numRows));
6245     PetscCall(ISGetIndices(is, &rows));
6246   }
6247   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6248   if (is) PetscCall(ISRestoreIndices(is, &rows));
6249   PetscFunctionReturn(PETSC_SUCCESS);
6250 }
6251 
6252 /*@
6253    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6254    of a set of rows of a matrix. These rows must be local to the process.
6255 
6256    Collective
6257 
6258    Input Parameters:
6259 +  mat - the matrix
6260 .  numRows - the number of rows to remove
6261 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6262 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6263 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6264 -  b - optional vector of right hand side, that will be adjusted by provided solution
6265 
6266    Level: intermediate
6267 
6268    Notes:
6269    See `MatZeroRows()` for details on how this routine operates.
6270 
6271    The grid coordinates are across the entire grid, not just the local portion
6272 
6273    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6274    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6275    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6276    `DM_BOUNDARY_PERIODIC` boundary type.
6277 
6278    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
6279    a single value per point) you can skip filling those indices.
6280 
6281    Fortran Note:
6282    `idxm` and `idxn` should be declared as
6283 $     MatStencil idxm(4,m)
6284    and the values inserted using
6285 .vb
6286     idxm(MatStencil_i,1) = i
6287     idxm(MatStencil_j,1) = j
6288     idxm(MatStencil_k,1) = k
6289     idxm(MatStencil_c,1) = c
6290    etc
6291 .ve
6292 
6293 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6294           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6295 @*/
6296 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6297 {
6298   PetscInt  dim    = mat->stencil.dim;
6299   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6300   PetscInt *dims   = mat->stencil.dims + 1;
6301   PetscInt *starts = mat->stencil.starts;
6302   PetscInt *dxm    = (PetscInt *)rows;
6303   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6304 
6305   PetscFunctionBegin;
6306   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6307   PetscValidType(mat, 1);
6308   if (numRows) PetscValidPointer(rows, 3);
6309 
6310   PetscCall(PetscMalloc1(numRows, &jdxm));
6311   for (i = 0; i < numRows; ++i) {
6312     /* Skip unused dimensions (they are ordered k, j, i, c) */
6313     for (j = 0; j < 3 - sdim; ++j) dxm++;
6314     /* Local index in X dir */
6315     tmp = *dxm++ - starts[0];
6316     /* Loop over remaining dimensions */
6317     for (j = 0; j < dim - 1; ++j) {
6318       /* If nonlocal, set index to be negative */
6319       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6320       /* Update local index */
6321       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6322     }
6323     /* Skip component slot if necessary */
6324     if (mat->stencil.noc) dxm++;
6325     /* Local row number */
6326     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6327   }
6328   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6329   PetscCall(PetscFree(jdxm));
6330   PetscFunctionReturn(PETSC_SUCCESS);
6331 }
6332 
6333 /*@
6334    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6335    of a set of rows and columns of a matrix.
6336 
6337    Collective
6338 
6339    Input Parameters:
6340 +  mat - the matrix
6341 .  numRows - the number of rows/columns to remove
6342 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6343 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6344 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6345 -  b - optional vector of right hand side, that will be adjusted by provided solution
6346 
6347    Level: intermediate
6348 
6349    Notes:
6350    See `MatZeroRowsColumns()` for details on how this routine operates.
6351 
6352    The grid coordinates are across the entire grid, not just the local portion
6353 
6354    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6355    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6356    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6357    `DM_BOUNDARY_PERIODIC` boundary type.
6358 
6359    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
6360    a single value per point) you can skip filling those indices.
6361 
6362    Fortran Note:
6363    `idxm` and `idxn` should be declared as
6364 $     MatStencil idxm(4,m)
6365    and the values inserted using
6366 .vb
6367     idxm(MatStencil_i,1) = i
6368     idxm(MatStencil_j,1) = j
6369     idxm(MatStencil_k,1) = k
6370     idxm(MatStencil_c,1) = c
6371     etc
6372 .ve
6373 
6374 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6375           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6376 @*/
6377 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6378 {
6379   PetscInt  dim    = mat->stencil.dim;
6380   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6381   PetscInt *dims   = mat->stencil.dims + 1;
6382   PetscInt *starts = mat->stencil.starts;
6383   PetscInt *dxm    = (PetscInt *)rows;
6384   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6385 
6386   PetscFunctionBegin;
6387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6388   PetscValidType(mat, 1);
6389   if (numRows) PetscValidPointer(rows, 3);
6390 
6391   PetscCall(PetscMalloc1(numRows, &jdxm));
6392   for (i = 0; i < numRows; ++i) {
6393     /* Skip unused dimensions (they are ordered k, j, i, c) */
6394     for (j = 0; j < 3 - sdim; ++j) dxm++;
6395     /* Local index in X dir */
6396     tmp = *dxm++ - starts[0];
6397     /* Loop over remaining dimensions */
6398     for (j = 0; j < dim - 1; ++j) {
6399       /* If nonlocal, set index to be negative */
6400       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6401       /* Update local index */
6402       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6403     }
6404     /* Skip component slot if necessary */
6405     if (mat->stencil.noc) dxm++;
6406     /* Local row number */
6407     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6408   }
6409   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6410   PetscCall(PetscFree(jdxm));
6411   PetscFunctionReturn(PETSC_SUCCESS);
6412 }
6413 
6414 /*@C
6415    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6416    of a set of rows of a matrix; using local numbering of rows.
6417 
6418    Collective
6419 
6420    Input Parameters:
6421 +  mat - the matrix
6422 .  numRows - the number of rows to remove
6423 .  rows - the local row indices
6424 .  diag - value put in all diagonals of eliminated rows
6425 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6426 -  b - optional vector of right hand side, that will be adjusted by provided solution
6427 
6428    Level: intermediate
6429 
6430    Notes:
6431    Before calling `MatZeroRowsLocal()`, the user must first set the
6432    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6433 
6434    See `MatZeroRows()` for details on how this routine operates.
6435 
6436 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6437           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6438 @*/
6439 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6440 {
6441   PetscFunctionBegin;
6442   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6443   PetscValidType(mat, 1);
6444   if (numRows) PetscValidIntPointer(rows, 3);
6445   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6446   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6447   MatCheckPreallocated(mat, 1);
6448 
6449   if (mat->ops->zerorowslocal) {
6450     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6451   } else {
6452     IS              is, newis;
6453     const PetscInt *newRows;
6454 
6455     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6456     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6457     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6458     PetscCall(ISGetIndices(newis, &newRows));
6459     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6460     PetscCall(ISRestoreIndices(newis, &newRows));
6461     PetscCall(ISDestroy(&newis));
6462     PetscCall(ISDestroy(&is));
6463   }
6464   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6465   PetscFunctionReturn(PETSC_SUCCESS);
6466 }
6467 
6468 /*@
6469    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6470    of a set of rows of a matrix; using local numbering of rows.
6471 
6472    Collective
6473 
6474    Input Parameters:
6475 +  mat - the matrix
6476 .  is - index set of rows to remove
6477 .  diag - value put in all diagonals of eliminated rows
6478 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6479 -  b - optional vector of right hand side, that will be adjusted by provided solution
6480 
6481    Level: intermediate
6482 
6483    Notes:
6484    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6485    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6486 
6487    See `MatZeroRows()` for details on how this routine operates.
6488 
6489 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6490           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6491 @*/
6492 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6493 {
6494   PetscInt        numRows;
6495   const PetscInt *rows;
6496 
6497   PetscFunctionBegin;
6498   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6499   PetscValidType(mat, 1);
6500   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6503   MatCheckPreallocated(mat, 1);
6504 
6505   PetscCall(ISGetLocalSize(is, &numRows));
6506   PetscCall(ISGetIndices(is, &rows));
6507   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6508   PetscCall(ISRestoreIndices(is, &rows));
6509   PetscFunctionReturn(PETSC_SUCCESS);
6510 }
6511 
6512 /*@
6513    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6514    of a set of rows and columns of a matrix; using local numbering of rows.
6515 
6516    Collective
6517 
6518    Input Parameters:
6519 +  mat - the matrix
6520 .  numRows - the number of rows to remove
6521 .  rows - the global row indices
6522 .  diag - value put in all diagonals of eliminated rows
6523 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6524 -  b - optional vector of right hand side, that will be adjusted by provided solution
6525 
6526    Level: intermediate
6527 
6528    Notes:
6529    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6530    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6531 
6532    See `MatZeroRowsColumns()` for details on how this routine operates.
6533 
6534 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6535           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6536 @*/
6537 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6538 {
6539   IS              is, newis;
6540   const PetscInt *newRows;
6541 
6542   PetscFunctionBegin;
6543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6544   PetscValidType(mat, 1);
6545   if (numRows) PetscValidIntPointer(rows, 3);
6546   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6547   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6548   MatCheckPreallocated(mat, 1);
6549 
6550   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6551   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6552   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6553   PetscCall(ISGetIndices(newis, &newRows));
6554   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6555   PetscCall(ISRestoreIndices(newis, &newRows));
6556   PetscCall(ISDestroy(&newis));
6557   PetscCall(ISDestroy(&is));
6558   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6559   PetscFunctionReturn(PETSC_SUCCESS);
6560 }
6561 
6562 /*@
6563    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6564    of a set of rows and columns of a matrix; using local numbering of rows.
6565 
6566    Collective
6567 
6568    Input Parameters:
6569 +  mat - the matrix
6570 .  is - index set of rows to remove
6571 .  diag - value put in all diagonals of eliminated rows
6572 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6573 -  b - optional vector of right hand side, that will be adjusted by provided solution
6574 
6575    Level: intermediate
6576 
6577    Notes:
6578    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6579    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6580 
6581    See `MatZeroRowsColumns()` for details on how this routine operates.
6582 
6583 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6584           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6585 @*/
6586 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6587 {
6588   PetscInt        numRows;
6589   const PetscInt *rows;
6590 
6591   PetscFunctionBegin;
6592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6593   PetscValidType(mat, 1);
6594   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6597   MatCheckPreallocated(mat, 1);
6598 
6599   PetscCall(ISGetLocalSize(is, &numRows));
6600   PetscCall(ISGetIndices(is, &rows));
6601   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6602   PetscCall(ISRestoreIndices(is, &rows));
6603   PetscFunctionReturn(PETSC_SUCCESS);
6604 }
6605 
6606 /*@C
6607    MatGetSize - Returns the numbers of rows and columns in a matrix.
6608 
6609    Not Collective
6610 
6611    Input Parameter:
6612 .  mat - the matrix
6613 
6614    Output Parameters:
6615 +  m - the number of global rows
6616 -  n - the number of global columns
6617 
6618    Level: beginner
6619 
6620    Note:
6621    Both output parameters can be `NULL` on input.
6622 
6623 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6624 @*/
6625 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6626 {
6627   PetscFunctionBegin;
6628   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6629   if (m) *m = mat->rmap->N;
6630   if (n) *n = mat->cmap->N;
6631   PetscFunctionReturn(PETSC_SUCCESS);
6632 }
6633 
6634 /*@C
6635    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6636    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6637 
6638    Not Collective
6639 
6640    Input Parameter:
6641 .  mat - the matrix
6642 
6643    Output Parameters:
6644 +  m - the number of local rows, use `NULL` to not obtain this value
6645 -  n - the number of local columns, use `NULL` to not obtain this value
6646 
6647    Level: beginner
6648 
6649 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6650 @*/
6651 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6652 {
6653   PetscFunctionBegin;
6654   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6655   if (m) PetscValidIntPointer(m, 2);
6656   if (n) PetscValidIntPointer(n, 3);
6657   if (m) *m = mat->rmap->n;
6658   if (n) *n = mat->cmap->n;
6659   PetscFunctionReturn(PETSC_SUCCESS);
6660 }
6661 
6662 /*@C
6663    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6664    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6665 
6666    Not Collective, unless matrix has not been allocated, then collective
6667 
6668    Input Parameter:
6669 .  mat - the matrix
6670 
6671    Output Parameters:
6672 +  m - the global index of the first local column, use `NULL` to not obtain this value
6673 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6674 
6675    Level: developer
6676 
6677 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6678 @*/
6679 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6680 {
6681   PetscFunctionBegin;
6682   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6683   PetscValidType(mat, 1);
6684   if (m) PetscValidIntPointer(m, 2);
6685   if (n) PetscValidIntPointer(n, 3);
6686   MatCheckPreallocated(mat, 1);
6687   if (m) *m = mat->cmap->rstart;
6688   if (n) *n = mat->cmap->rend;
6689   PetscFunctionReturn(PETSC_SUCCESS);
6690 }
6691 
6692 /*@C
6693    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6694    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
6695    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6696 
6697    Not Collective
6698 
6699    Input Parameter:
6700 .  mat - the matrix
6701 
6702    Output Parameters:
6703 +  m - the global index of the first local row, use `NULL` to not obtain this value
6704 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6705 
6706    Level: beginner
6707 
6708    Note:
6709   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6710   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6711   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6712 
6713 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6714           `PetscLayout`
6715 @*/
6716 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6717 {
6718   PetscFunctionBegin;
6719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6720   PetscValidType(mat, 1);
6721   if (m) PetscValidIntPointer(m, 2);
6722   if (n) PetscValidIntPointer(n, 3);
6723   MatCheckPreallocated(mat, 1);
6724   if (m) *m = mat->rmap->rstart;
6725   if (n) *n = mat->rmap->rend;
6726   PetscFunctionReturn(PETSC_SUCCESS);
6727 }
6728 
6729 /*@C
6730    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6731    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
6732    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6733 
6734    Not Collective, unless matrix has not been allocated
6735 
6736    Input Parameter:
6737 .  mat - the matrix
6738 
6739    Output Parameter:
6740 .  ranges - start of each processors portion plus one more than the total length at the end
6741 
6742    Level: beginner
6743 
6744 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6745 @*/
6746 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6747 {
6748   PetscFunctionBegin;
6749   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6750   PetscValidType(mat, 1);
6751   MatCheckPreallocated(mat, 1);
6752   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6753   PetscFunctionReturn(PETSC_SUCCESS);
6754 }
6755 
6756 /*@C
6757    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6758    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6759 
6760    Not Collective, unless matrix has not been allocated
6761 
6762    Input Parameter:
6763 .  mat - the matrix
6764 
6765    Output Parameter:
6766 .  ranges - start of each processors portion plus one more then the total length at the end
6767 
6768    Level: beginner
6769 
6770 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6771 @*/
6772 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6773 {
6774   PetscFunctionBegin;
6775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6776   PetscValidType(mat, 1);
6777   MatCheckPreallocated(mat, 1);
6778   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6779   PetscFunctionReturn(PETSC_SUCCESS);
6780 }
6781 
6782 /*@C
6783    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6784    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6785    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6786 
6787    Not Collective
6788 
6789    Input Parameter:
6790 .  A - matrix
6791 
6792    Output Parameters:
6793 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6794 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6795 
6796    Level: intermediate
6797 
6798 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6799 @*/
6800 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6801 {
6802   PetscErrorCode (*f)(Mat, IS *, IS *);
6803 
6804   PetscFunctionBegin;
6805   MatCheckPreallocated(A, 1);
6806   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6807   if (f) {
6808     PetscCall((*f)(A, rows, cols));
6809   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6810     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6811     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6812   }
6813   PetscFunctionReturn(PETSC_SUCCESS);
6814 }
6815 
6816 /*@C
6817    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6818    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6819    to complete the factorization.
6820 
6821    Collective
6822 
6823    Input Parameters:
6824 +  fact - the factorized matrix obtained with `MatGetFactor()`
6825 .  mat - the matrix
6826 .  row - row permutation
6827 .  col - column permutation
6828 -  info - structure containing
6829 .vb
6830       levels - number of levels of fill.
6831       expected fill - as ratio of original fill.
6832       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6833                 missing diagonal entries)
6834 .ve
6835 
6836    Level: developer
6837 
6838    Notes:
6839    See [Matrix Factorization](sec_matfactor) for additional information.
6840 
6841    Most users should employ the `KSP` interface for linear solvers
6842    instead of working directly with matrix algebra routines such as this.
6843    See, e.g., `KSPCreate()`.
6844 
6845    Uses the definition of level of fill as in Y. Saad, 2003
6846 
6847    Developer Note:
6848    The Fortran interface is not autogenerated as the
6849    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6850 
6851    References:
6852 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6853 
6854 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6855           `MatGetOrdering()`, `MatFactorInfo`
6856 @*/
6857 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6858 {
6859   PetscFunctionBegin;
6860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6861   PetscValidType(mat, 2);
6862   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6863   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6864   PetscValidPointer(info, 5);
6865   PetscValidPointer(fact, 1);
6866   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6867   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6868   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6869   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6870   MatCheckPreallocated(mat, 2);
6871 
6872   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6873   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6874   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6875   PetscFunctionReturn(PETSC_SUCCESS);
6876 }
6877 
6878 /*@C
6879    MatICCFactorSymbolic - Performs symbolic incomplete
6880    Cholesky factorization for a symmetric matrix.  Use
6881    `MatCholeskyFactorNumeric()` to complete the factorization.
6882 
6883    Collective
6884 
6885    Input Parameters:
6886 +  fact - the factorized matrix obtained with `MatGetFactor()`
6887 .  mat - the matrix to be factored
6888 .  perm - row and column permutation
6889 -  info - structure containing
6890 .vb
6891       levels - number of levels of fill.
6892       expected fill - as ratio of original fill.
6893 .ve
6894 
6895    Level: developer
6896 
6897    Notes:
6898    Most users should employ the `KSP` interface for linear solvers
6899    instead of working directly with matrix algebra routines such as this.
6900    See, e.g., `KSPCreate()`.
6901 
6902    This uses the definition of level of fill as in Y. Saad, 2003
6903 
6904    Developer Note:
6905    The Fortran interface is not autogenerated as the
6906    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6907 
6908    References:
6909 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6910 
6911 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6912 @*/
6913 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6914 {
6915   PetscFunctionBegin;
6916   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6917   PetscValidType(mat, 2);
6918   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6919   PetscValidPointer(info, 4);
6920   PetscValidPointer(fact, 1);
6921   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6922   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6923   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6924   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6925   MatCheckPreallocated(mat, 2);
6926 
6927   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6928   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6929   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6930   PetscFunctionReturn(PETSC_SUCCESS);
6931 }
6932 
6933 /*@C
6934    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6935    points to an array of valid matrices, they may be reused to store the new
6936    submatrices.
6937 
6938    Collective
6939 
6940    Input Parameters:
6941 +  mat - the matrix
6942 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6943 .  irow - index set of rows to extract
6944 .  icol - index set of columns to extract
6945 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6946 
6947    Output Parameter:
6948 .  submat - the array of submatrices
6949 
6950    Level: advanced
6951 
6952    Notes:
6953    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6954    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6955    to extract a parallel submatrix.
6956 
6957    Some matrix types place restrictions on the row and column
6958    indices, such as that they be sorted or that they be equal to each other.
6959 
6960    The index sets may not have duplicate entries.
6961 
6962    When extracting submatrices from a parallel matrix, each processor can
6963    form a different submatrix by setting the rows and columns of its
6964    individual index sets according to the local submatrix desired.
6965 
6966    When finished using the submatrices, the user should destroy
6967    them with `MatDestroySubMatrices()`.
6968 
6969    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6970    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6971 
6972    This routine creates the matrices in submat; you should NOT create them before
6973    calling it. It also allocates the array of matrix pointers submat.
6974 
6975    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6976    request one row/column in a block, they must request all rows/columns that are in
6977    that block. For example, if the block size is 2 you cannot request just row 0 and
6978    column 0.
6979 
6980    Fortran Note:
6981    The Fortran interface is slightly different from that given below; it
6982    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6983 
6984 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6985 @*/
6986 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6987 {
6988   PetscInt  i;
6989   PetscBool eq;
6990 
6991   PetscFunctionBegin;
6992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6993   PetscValidType(mat, 1);
6994   if (n) {
6995     PetscValidPointer(irow, 3);
6996     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6997     PetscValidPointer(icol, 4);
6998     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6999   }
7000   PetscValidPointer(submat, 6);
7001   if (n && scall == MAT_REUSE_MATRIX) {
7002     PetscValidPointer(*submat, 6);
7003     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7004   }
7005   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7006   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7007   MatCheckPreallocated(mat, 1);
7008   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7009   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7010   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7011   for (i = 0; i < n; i++) {
7012     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7013     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7014     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7015 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7016     if (mat->boundtocpu && mat->bindingpropagates) {
7017       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7018       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7019     }
7020 #endif
7021   }
7022   PetscFunctionReturn(PETSC_SUCCESS);
7023 }
7024 
7025 /*@C
7026    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7027 
7028    Collective
7029 
7030    Input Parameters:
7031 +  mat - the matrix
7032 .  n   - the number of submatrixes to be extracted
7033 .  irow - index set of rows to extract
7034 .  icol - index set of columns to extract
7035 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7036 
7037    Output Parameter:
7038 .  submat - the array of submatrices
7039 
7040    Level: advanced
7041 
7042    Note:
7043    This is used by `PCGASM`
7044 
7045 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7046 @*/
7047 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7048 {
7049   PetscInt  i;
7050   PetscBool eq;
7051 
7052   PetscFunctionBegin;
7053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7054   PetscValidType(mat, 1);
7055   if (n) {
7056     PetscValidPointer(irow, 3);
7057     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7058     PetscValidPointer(icol, 4);
7059     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7060   }
7061   PetscValidPointer(submat, 6);
7062   if (n && scall == MAT_REUSE_MATRIX) {
7063     PetscValidPointer(*submat, 6);
7064     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7065   }
7066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7067   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7068   MatCheckPreallocated(mat, 1);
7069 
7070   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7071   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7072   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7073   for (i = 0; i < n; i++) {
7074     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7075     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7076   }
7077   PetscFunctionReturn(PETSC_SUCCESS);
7078 }
7079 
7080 /*@C
7081    MatDestroyMatrices - Destroys an array of matrices.
7082 
7083    Collective
7084 
7085    Input Parameters:
7086 +  n - the number of local matrices
7087 -  mat - the matrices (this is a pointer to the array of matrices)
7088 
7089    Level: advanced
7090 
7091     Note:
7092     Frees not only the matrices, but also the array that contains the matrices
7093 
7094     Fortran Note:
7095     This does not free the array.
7096 
7097 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7098 @*/
7099 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7100 {
7101   PetscInt i;
7102 
7103   PetscFunctionBegin;
7104   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7105   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7106   PetscValidPointer(mat, 2);
7107 
7108   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7109 
7110   /* memory is allocated even if n = 0 */
7111   PetscCall(PetscFree(*mat));
7112   PetscFunctionReturn(PETSC_SUCCESS);
7113 }
7114 
7115 /*@C
7116    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7117 
7118    Collective
7119 
7120    Input Parameters:
7121 +  n - the number of local matrices
7122 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7123                        sequence of `MatCreateSubMatrices()`)
7124 
7125    Level: advanced
7126 
7127     Note:
7128     Frees not only the matrices, but also the array that contains the matrices
7129 
7130     Fortran Note:
7131     This does not free the array.
7132 
7133 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7134 @*/
7135 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7136 {
7137   Mat mat0;
7138 
7139   PetscFunctionBegin;
7140   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7141   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7142   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7143   PetscValidPointer(mat, 2);
7144 
7145   mat0 = (*mat)[0];
7146   if (mat0 && mat0->ops->destroysubmatrices) {
7147     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7148   } else {
7149     PetscCall(MatDestroyMatrices(n, mat));
7150   }
7151   PetscFunctionReturn(PETSC_SUCCESS);
7152 }
7153 
7154 /*@C
7155    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7156 
7157    Collective
7158 
7159    Input Parameter:
7160 .  mat - the matrix
7161 
7162    Output Parameter:
7163 .  matstruct - the sequential matrix with the nonzero structure of mat
7164 
7165   Level: developer
7166 
7167 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7168 @*/
7169 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7170 {
7171   PetscFunctionBegin;
7172   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7173   PetscValidPointer(matstruct, 2);
7174 
7175   PetscValidType(mat, 1);
7176   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7177   MatCheckPreallocated(mat, 1);
7178 
7179   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7180   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7181   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7182   PetscFunctionReturn(PETSC_SUCCESS);
7183 }
7184 
7185 /*@C
7186    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7187 
7188    Collective
7189 
7190    Input Parameter:
7191 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7192                        sequence of `MatGetSequentialNonzeroStructure()`)
7193 
7194    Level: advanced
7195 
7196     Note:
7197     Frees not only the matrices, but also the array that contains the matrices
7198 
7199 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7200 @*/
7201 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7202 {
7203   PetscFunctionBegin;
7204   PetscValidPointer(mat, 1);
7205   PetscCall(MatDestroy(mat));
7206   PetscFunctionReturn(PETSC_SUCCESS);
7207 }
7208 
7209 /*@
7210    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7211    replaces the index sets by larger ones that represent submatrices with
7212    additional overlap.
7213 
7214    Collective
7215 
7216    Input Parameters:
7217 +  mat - the matrix
7218 .  n   - the number of index sets
7219 .  is  - the array of index sets (these index sets will changed during the call)
7220 -  ov  - the additional overlap requested
7221 
7222    Options Database Key:
7223 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7224 
7225    Level: developer
7226 
7227    Note:
7228    The computed overlap preserves the matrix block sizes when the blocks are square.
7229    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7230    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7231 
7232 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7233 @*/
7234 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7235 {
7236   PetscInt i, bs, cbs;
7237 
7238   PetscFunctionBegin;
7239   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7240   PetscValidType(mat, 1);
7241   PetscValidLogicalCollectiveInt(mat, n, 2);
7242   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7243   if (n) {
7244     PetscValidPointer(is, 3);
7245     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7246   }
7247   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7248   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7249   MatCheckPreallocated(mat, 1);
7250 
7251   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7252   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7253   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7254   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7255   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7256   if (bs == cbs) {
7257     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7258   }
7259   PetscFunctionReturn(PETSC_SUCCESS);
7260 }
7261 
7262 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7263 
7264 /*@
7265    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7266    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7267    additional overlap.
7268 
7269    Collective
7270 
7271    Input Parameters:
7272 +  mat - the matrix
7273 .  n   - the number of index sets
7274 .  is  - the array of index sets (these index sets will changed during the call)
7275 -  ov  - the additional overlap requested
7276 
7277 `   Options Database Key:
7278 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7279 
7280    Level: developer
7281 
7282 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7283 @*/
7284 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7285 {
7286   PetscInt i;
7287 
7288   PetscFunctionBegin;
7289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7290   PetscValidType(mat, 1);
7291   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7292   if (n) {
7293     PetscValidPointer(is, 3);
7294     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7295   }
7296   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7297   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7298   MatCheckPreallocated(mat, 1);
7299   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7300   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7301   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7302   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7303   PetscFunctionReturn(PETSC_SUCCESS);
7304 }
7305 
7306 /*@
7307    MatGetBlockSize - Returns the matrix block size.
7308 
7309    Not Collective
7310 
7311    Input Parameter:
7312 .  mat - the matrix
7313 
7314    Output Parameter:
7315 .  bs - block size
7316 
7317    Level: intermediate
7318 
7319    Notes:
7320     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7321 
7322    If the block size has not been set yet this routine returns 1.
7323 
7324 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7325 @*/
7326 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7327 {
7328   PetscFunctionBegin;
7329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7330   PetscValidIntPointer(bs, 2);
7331   *bs = PetscAbs(mat->rmap->bs);
7332   PetscFunctionReturn(PETSC_SUCCESS);
7333 }
7334 
7335 /*@
7336    MatGetBlockSizes - Returns the matrix block row and column sizes.
7337 
7338    Not Collective
7339 
7340    Input Parameter:
7341 .  mat - the matrix
7342 
7343    Output Parameters:
7344 +  rbs - row block size
7345 -  cbs - column block size
7346 
7347    Level: intermediate
7348 
7349    Notes:
7350     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7351     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7352 
7353    If a block size has not been set yet this routine returns 1.
7354 
7355 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7356 @*/
7357 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7358 {
7359   PetscFunctionBegin;
7360   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7361   if (rbs) PetscValidIntPointer(rbs, 2);
7362   if (cbs) PetscValidIntPointer(cbs, 3);
7363   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7364   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7365   PetscFunctionReturn(PETSC_SUCCESS);
7366 }
7367 
7368 /*@
7369    MatSetBlockSize - Sets the matrix block size.
7370 
7371    Logically Collective
7372 
7373    Input Parameters:
7374 +  mat - the matrix
7375 -  bs - block size
7376 
7377    Level: intermediate
7378 
7379    Notes:
7380     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7381     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7382 
7383     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7384     is compatible with the matrix local sizes.
7385 
7386 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7387 @*/
7388 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7389 {
7390   PetscFunctionBegin;
7391   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7392   PetscValidLogicalCollectiveInt(mat, bs, 2);
7393   PetscCall(MatSetBlockSizes(mat, bs, bs));
7394   PetscFunctionReturn(PETSC_SUCCESS);
7395 }
7396 
7397 typedef struct {
7398   PetscInt         n;
7399   IS              *is;
7400   Mat             *mat;
7401   PetscObjectState nonzerostate;
7402   Mat              C;
7403 } EnvelopeData;
7404 
7405 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7406 {
7407   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7408   PetscCall(PetscFree(edata->is));
7409   PetscCall(PetscFree(edata));
7410   return PETSC_SUCCESS;
7411 }
7412 
7413 /*
7414    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7415          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7416 
7417    Collective
7418 
7419    Input Parameter:
7420 .  mat - the matrix
7421 
7422    Notes:
7423      There can be zeros within the blocks
7424 
7425      The blocks can overlap between processes, including laying on more than two processes
7426 
7427 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7428 */
7429 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7430 {
7431   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7432   PetscInt          *diag, *odiag, sc;
7433   VecScatter         scatter;
7434   PetscScalar       *seqv;
7435   const PetscScalar *parv;
7436   const PetscInt    *ia, *ja;
7437   PetscBool          set, flag, done;
7438   Mat                AA = mat, A;
7439   MPI_Comm           comm;
7440   PetscMPIInt        rank, size, tag;
7441   MPI_Status         status;
7442   PetscContainer     container;
7443   EnvelopeData      *edata;
7444   Vec                seq, par;
7445   IS                 isglobal;
7446 
7447   PetscFunctionBegin;
7448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7449   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7450   if (!set || !flag) {
7451     /* TOO: only needs nonzero structure of transpose */
7452     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7453     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7454   }
7455   PetscCall(MatAIJGetLocalMat(AA, &A));
7456   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7457   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7458 
7459   PetscCall(MatGetLocalSize(mat, &n, NULL));
7460   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7461   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7462   PetscCallMPI(MPI_Comm_size(comm, &size));
7463   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7464 
7465   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7466 
7467   if (rank > 0) {
7468     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7469     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7470   }
7471   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7472   for (i = 0; i < n; i++) {
7473     env = PetscMax(env, ja[ia[i + 1] - 1]);
7474     II  = rstart + i;
7475     if (env == II) {
7476       starts[lblocks]  = tbs;
7477       sizes[lblocks++] = 1 + II - tbs;
7478       tbs              = 1 + II;
7479     }
7480   }
7481   if (rank < size - 1) {
7482     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7483     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7484   }
7485 
7486   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7487   if (!set || !flag) PetscCall(MatDestroy(&AA));
7488   PetscCall(MatDestroy(&A));
7489 
7490   PetscCall(PetscNew(&edata));
7491   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7492   edata->n = lblocks;
7493   /* create IS needed for extracting blocks from the original matrix */
7494   PetscCall(PetscMalloc1(lblocks, &edata->is));
7495   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7496 
7497   /* Create the resulting inverse matrix structure with preallocation information */
7498   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7499   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7500   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7501   PetscCall(MatSetType(edata->C, MATAIJ));
7502 
7503   /* Communicate the start and end of each row, from each block to the correct rank */
7504   /* TODO: Use PetscSF instead of VecScatter */
7505   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7506   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7507   PetscCall(VecGetArrayWrite(seq, &seqv));
7508   for (PetscInt i = 0; i < lblocks; i++) {
7509     for (PetscInt j = 0; j < sizes[i]; j++) {
7510       seqv[cnt]     = starts[i];
7511       seqv[cnt + 1] = starts[i] + sizes[i];
7512       cnt += 2;
7513     }
7514   }
7515   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7516   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7517   sc -= cnt;
7518   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7519   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7520   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7521   PetscCall(ISDestroy(&isglobal));
7522   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7523   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7524   PetscCall(VecScatterDestroy(&scatter));
7525   PetscCall(VecDestroy(&seq));
7526   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7527   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7528   PetscCall(VecGetArrayRead(par, &parv));
7529   cnt = 0;
7530   PetscCall(MatGetSize(mat, NULL, &n));
7531   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7532     PetscInt start, end, d = 0, od = 0;
7533 
7534     start = (PetscInt)PetscRealPart(parv[cnt]);
7535     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7536     cnt += 2;
7537 
7538     if (start < cstart) {
7539       od += cstart - start + n - cend;
7540       d += cend - cstart;
7541     } else if (start < cend) {
7542       od += n - cend;
7543       d += cend - start;
7544     } else od += n - start;
7545     if (end <= cstart) {
7546       od -= cstart - end + n - cend;
7547       d -= cend - cstart;
7548     } else if (end < cend) {
7549       od -= n - cend;
7550       d -= cend - end;
7551     } else od -= n - end;
7552 
7553     odiag[i] = od;
7554     diag[i]  = d;
7555   }
7556   PetscCall(VecRestoreArrayRead(par, &parv));
7557   PetscCall(VecDestroy(&par));
7558   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7559   PetscCall(PetscFree2(diag, odiag));
7560   PetscCall(PetscFree2(sizes, starts));
7561 
7562   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7563   PetscCall(PetscContainerSetPointer(container, edata));
7564   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7565   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7566   PetscCall(PetscObjectDereference((PetscObject)container));
7567   PetscFunctionReturn(PETSC_SUCCESS);
7568 }
7569 
7570 /*@
7571   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7572 
7573   Collective
7574 
7575   Input Parameters:
7576 + A - the matrix
7577 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7578 
7579   Output Parameter:
7580 . C - matrix with inverted block diagonal of `A`
7581 
7582   Level: advanced
7583 
7584   Note:
7585      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7586 
7587 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7588 @*/
7589 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7590 {
7591   PetscContainer   container;
7592   EnvelopeData    *edata;
7593   PetscObjectState nonzerostate;
7594 
7595   PetscFunctionBegin;
7596   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7597   if (!container) {
7598     PetscCall(MatComputeVariableBlockEnvelope(A));
7599     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7600   }
7601   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7602   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7603   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7604   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7605 
7606   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7607   *C = edata->C;
7608 
7609   for (PetscInt i = 0; i < edata->n; i++) {
7610     Mat          D;
7611     PetscScalar *dvalues;
7612 
7613     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7614     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7615     PetscCall(MatSeqDenseInvert(D));
7616     PetscCall(MatDenseGetArray(D, &dvalues));
7617     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7618     PetscCall(MatDestroy(&D));
7619   }
7620   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7621   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7622   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7623   PetscFunctionReturn(PETSC_SUCCESS);
7624 }
7625 
7626 /*@
7627    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7628 
7629    Logically Collective
7630 
7631    Input Parameters:
7632 +  mat - the matrix
7633 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7634 -  bsizes - the block sizes
7635 
7636    Level: intermediate
7637 
7638    Notes:
7639     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7640 
7641     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.
7642 
7643 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7644           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7645 @*/
7646 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7647 {
7648   PetscInt i, ncnt = 0, nlocal;
7649 
7650   PetscFunctionBegin;
7651   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7652   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7653   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7654   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7655   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);
7656   PetscCall(PetscFree(mat->bsizes));
7657   mat->nblocks = nblocks;
7658   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7659   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7660   PetscFunctionReturn(PETSC_SUCCESS);
7661 }
7662 
7663 /*@C
7664    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7665 
7666    Logically Collective; No Fortran Support
7667 
7668    Input Parameter:
7669 .  mat - the matrix
7670 
7671    Output Parameters:
7672 +  nblocks - the number of blocks on this process
7673 -  bsizes - the block sizes
7674 
7675    Level: intermediate
7676 
7677 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7678 @*/
7679 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7680 {
7681   PetscFunctionBegin;
7682   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7683   *nblocks = mat->nblocks;
7684   *bsizes  = mat->bsizes;
7685   PetscFunctionReturn(PETSC_SUCCESS);
7686 }
7687 
7688 /*@
7689    MatSetBlockSizes - Sets the matrix block row and column sizes.
7690 
7691    Logically Collective
7692 
7693    Input Parameters:
7694 +  mat - the matrix
7695 .  rbs - row block size
7696 -  cbs - column block size
7697 
7698    Level: intermediate
7699 
7700    Notes:
7701     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7702     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7703     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7704 
7705     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7706     are compatible with the matrix local sizes.
7707 
7708     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7709 
7710 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7711 @*/
7712 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7713 {
7714   PetscFunctionBegin;
7715   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7716   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7717   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7718   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7719   if (mat->rmap->refcnt) {
7720     ISLocalToGlobalMapping l2g  = NULL;
7721     PetscLayout            nmap = NULL;
7722 
7723     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7724     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7725     PetscCall(PetscLayoutDestroy(&mat->rmap));
7726     mat->rmap          = nmap;
7727     mat->rmap->mapping = l2g;
7728   }
7729   if (mat->cmap->refcnt) {
7730     ISLocalToGlobalMapping l2g  = NULL;
7731     PetscLayout            nmap = NULL;
7732 
7733     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7734     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7735     PetscCall(PetscLayoutDestroy(&mat->cmap));
7736     mat->cmap          = nmap;
7737     mat->cmap->mapping = l2g;
7738   }
7739   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7740   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7741   PetscFunctionReturn(PETSC_SUCCESS);
7742 }
7743 
7744 /*@
7745    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7746 
7747    Logically Collective
7748 
7749    Input Parameters:
7750 +  mat - the matrix
7751 .  fromRow - matrix from which to copy row block size
7752 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7753 
7754    Level: developer
7755 
7756 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7757 @*/
7758 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7759 {
7760   PetscFunctionBegin;
7761   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7762   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7763   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7764   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7765   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7766   PetscFunctionReturn(PETSC_SUCCESS);
7767 }
7768 
7769 /*@
7770    MatResidual - Default routine to calculate the residual r = b - Ax
7771 
7772    Collective
7773 
7774    Input Parameters:
7775 +  mat - the matrix
7776 .  b   - the right-hand-side
7777 -  x   - the approximate solution
7778 
7779    Output Parameter:
7780 .  r - location to store the residual
7781 
7782    Level: developer
7783 
7784 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7785 @*/
7786 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7787 {
7788   PetscFunctionBegin;
7789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7790   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7791   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7792   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7793   PetscValidType(mat, 1);
7794   MatCheckPreallocated(mat, 1);
7795   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7796   if (!mat->ops->residual) {
7797     PetscCall(MatMult(mat, x, r));
7798     PetscCall(VecAYPX(r, -1.0, b));
7799   } else {
7800     PetscUseTypeMethod(mat, residual, b, x, r);
7801   }
7802   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7803   PetscFunctionReturn(PETSC_SUCCESS);
7804 }
7805 
7806 /*MC
7807     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7808 
7809     Synopsis:
7810     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7811 
7812     Not Collective
7813 
7814     Input Parameters:
7815 +   A - the matrix
7816 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7817 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7818 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7819                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7820                  always used.
7821 
7822     Output Parameters:
7823 +   n - number of local rows in the (possibly compressed) matrix
7824 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7825 .   ja - the column indices
7826 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7827            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7828 
7829     Level: developer
7830 
7831     Note:
7832     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7833 
7834 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7835 M*/
7836 
7837 /*MC
7838     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7839 
7840     Synopsis:
7841     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7842 
7843     Not Collective
7844 
7845     Input Parameters:
7846 +   A - the  matrix
7847 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7848 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7849     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7850                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7851                  always used.
7852 .   n - number of local rows in the (possibly compressed) matrix
7853 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7854 .   ja - the column indices
7855 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7856            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7857 
7858     Level: developer
7859 
7860 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7861 M*/
7862 
7863 /*@C
7864     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7865 
7866    Collective
7867 
7868     Input Parameters:
7869 +   mat - the matrix
7870 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7871 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7872 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7873                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7874                  always used.
7875 
7876     Output Parameters:
7877 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7878 .   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
7879 .   ja - the column indices, use `NULL` if not needed
7880 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7881            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7882 
7883     Level: developer
7884 
7885     Notes:
7886     You CANNOT change any of the ia[] or ja[] values.
7887 
7888     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7889 
7890     Fortran Notes:
7891     Use
7892 .vb
7893     PetscInt, pointer :: ia(:),ja(:)
7894     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7895     ! Access the ith and jth entries via ia(i) and ja(j)
7896 .ve
7897    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7898 
7899 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7900 @*/
7901 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7902 {
7903   PetscFunctionBegin;
7904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7905   PetscValidType(mat, 1);
7906   if (n) PetscValidIntPointer(n, 5);
7907   if (ia) PetscValidPointer(ia, 6);
7908   if (ja) PetscValidPointer(ja, 7);
7909   if (done) PetscValidBoolPointer(done, 8);
7910   MatCheckPreallocated(mat, 1);
7911   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7912   else {
7913     if (done) *done = PETSC_TRUE;
7914     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7915     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7916     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7917   }
7918   PetscFunctionReturn(PETSC_SUCCESS);
7919 }
7920 
7921 /*@C
7922     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7923 
7924     Collective
7925 
7926     Input Parameters:
7927 +   mat - the matrix
7928 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7929 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7930                 symmetrized
7931 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7932                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7933                  always used.
7934 .   n - number of columns in the (possibly compressed) matrix
7935 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7936 -   ja - the row indices
7937 
7938     Output Parameter:
7939 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7940 
7941     Level: developer
7942 
7943 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7944 @*/
7945 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7946 {
7947   PetscFunctionBegin;
7948   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7949   PetscValidType(mat, 1);
7950   PetscValidIntPointer(n, 5);
7951   if (ia) PetscValidPointer(ia, 6);
7952   if (ja) PetscValidPointer(ja, 7);
7953   PetscValidBoolPointer(done, 8);
7954   MatCheckPreallocated(mat, 1);
7955   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7956   else {
7957     *done = PETSC_TRUE;
7958     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7959   }
7960   PetscFunctionReturn(PETSC_SUCCESS);
7961 }
7962 
7963 /*@C
7964     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7965 
7966     Collective
7967 
7968     Input Parameters:
7969 +   mat - the matrix
7970 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7971 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7972 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7973                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7974                  always used.
7975 .   n - size of (possibly compressed) matrix
7976 .   ia - the row pointers
7977 -   ja - the column indices
7978 
7979     Output Parameter:
7980 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7981 
7982     Level: developer
7983 
7984     Note:
7985     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7986     us of the array after it has been restored. If you pass `NULL`, it will
7987     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7988 
7989     Fortran Note:
7990    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
7991 
7992 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
7993 @*/
7994 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7995 {
7996   PetscFunctionBegin;
7997   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7998   PetscValidType(mat, 1);
7999   if (ia) PetscValidPointer(ia, 6);
8000   if (ja) PetscValidPointer(ja, 7);
8001   if (done) PetscValidBoolPointer(done, 8);
8002   MatCheckPreallocated(mat, 1);
8003 
8004   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8005   else {
8006     if (done) *done = PETSC_TRUE;
8007     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8008     if (n) *n = 0;
8009     if (ia) *ia = NULL;
8010     if (ja) *ja = NULL;
8011   }
8012   PetscFunctionReturn(PETSC_SUCCESS);
8013 }
8014 
8015 /*@C
8016     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8017 
8018     Collective
8019 
8020     Input Parameters:
8021 +   mat - the matrix
8022 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8023 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8024 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8025                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8026                  always used.
8027 
8028     Output Parameters:
8029 +   n - size of (possibly compressed) matrix
8030 .   ia - the column pointers
8031 .   ja - the row indices
8032 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8033 
8034     Level: developer
8035 
8036 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8037 @*/
8038 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8039 {
8040   PetscFunctionBegin;
8041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8042   PetscValidType(mat, 1);
8043   if (ia) PetscValidPointer(ia, 6);
8044   if (ja) PetscValidPointer(ja, 7);
8045   PetscValidBoolPointer(done, 8);
8046   MatCheckPreallocated(mat, 1);
8047 
8048   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8049   else {
8050     *done = PETSC_TRUE;
8051     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8052     if (n) *n = 0;
8053     if (ia) *ia = NULL;
8054     if (ja) *ja = NULL;
8055   }
8056   PetscFunctionReturn(PETSC_SUCCESS);
8057 }
8058 
8059 /*@C
8060     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8061 
8062     Collective
8063 
8064     Input Parameters:
8065 +   mat - the matrix
8066 .   ncolors - maximum color value
8067 .   n   - number of entries in colorarray
8068 -   colorarray - array indicating color for each column
8069 
8070     Output Parameter:
8071 .   iscoloring - coloring generated using colorarray information
8072 
8073     Level: developer
8074 
8075 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8076 @*/
8077 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8078 {
8079   PetscFunctionBegin;
8080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8081   PetscValidType(mat, 1);
8082   PetscValidIntPointer(colorarray, 4);
8083   PetscValidPointer(iscoloring, 5);
8084   MatCheckPreallocated(mat, 1);
8085 
8086   if (!mat->ops->coloringpatch) {
8087     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8088   } else {
8089     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8090   }
8091   PetscFunctionReturn(PETSC_SUCCESS);
8092 }
8093 
8094 /*@
8095    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8096 
8097    Logically Collective
8098 
8099    Input Parameter:
8100 .  mat - the factored matrix to be reset
8101 
8102    Level: developer
8103 
8104    Notes:
8105    This routine should be used only with factored matrices formed by in-place
8106    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8107    format).  This option can save memory, for example, when solving nonlinear
8108    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8109    ILU(0) preconditioner.
8110 
8111    One can specify in-place ILU(0) factorization by calling
8112 .vb
8113      PCType(pc,PCILU);
8114      PCFactorSeUseInPlace(pc);
8115 .ve
8116    or by using the options -pc_type ilu -pc_factor_in_place
8117 
8118    In-place factorization ILU(0) can also be used as a local
8119    solver for the blocks within the block Jacobi or additive Schwarz
8120    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8121    for details on setting local solver options.
8122 
8123    Most users should employ the `KSP` interface for linear solvers
8124    instead of working directly with matrix algebra routines such as this.
8125    See, e.g., `KSPCreate()`.
8126 
8127 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8128 @*/
8129 PetscErrorCode MatSetUnfactored(Mat mat)
8130 {
8131   PetscFunctionBegin;
8132   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8133   PetscValidType(mat, 1);
8134   MatCheckPreallocated(mat, 1);
8135   mat->factortype = MAT_FACTOR_NONE;
8136   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8137   PetscUseTypeMethod(mat, setunfactored);
8138   PetscFunctionReturn(PETSC_SUCCESS);
8139 }
8140 
8141 /*MC
8142     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8143 
8144     Synopsis:
8145     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8146 
8147     Not Collective
8148 
8149     Input Parameter:
8150 .   x - matrix
8151 
8152     Output Parameters:
8153 +   xx_v - the Fortran pointer to the array
8154 -   ierr - error code
8155 
8156     Example of Usage:
8157 .vb
8158       PetscScalar, pointer xx_v(:,:)
8159       ....
8160       call MatDenseGetArrayF90(x,xx_v,ierr)
8161       a = xx_v(3)
8162       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8163 .ve
8164 
8165     Level: advanced
8166 
8167 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8168 M*/
8169 
8170 /*MC
8171     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8172     accessed with `MatDenseGetArrayF90()`.
8173 
8174     Synopsis:
8175     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8176 
8177     Not Collective
8178 
8179     Input Parameters:
8180 +   x - matrix
8181 -   xx_v - the Fortran90 pointer to the array
8182 
8183     Output Parameter:
8184 .   ierr - error code
8185 
8186     Example of Usage:
8187 .vb
8188        PetscScalar, pointer xx_v(:,:)
8189        ....
8190        call MatDenseGetArrayF90(x,xx_v,ierr)
8191        a = xx_v(3)
8192        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8193 .ve
8194 
8195     Level: advanced
8196 
8197 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8198 M*/
8199 
8200 /*MC
8201     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8202 
8203     Synopsis:
8204     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8205 
8206     Not Collective
8207 
8208     Input Parameter:
8209 .   x - matrix
8210 
8211     Output Parameters:
8212 +   xx_v - the Fortran pointer to the array
8213 -   ierr - error code
8214 
8215     Example of Usage:
8216 .vb
8217       PetscScalar, pointer xx_v(:)
8218       ....
8219       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8220       a = xx_v(3)
8221       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8222 .ve
8223 
8224     Level: advanced
8225 
8226 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8227 M*/
8228 
8229 /*MC
8230     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8231     accessed with `MatSeqAIJGetArrayF90()`.
8232 
8233     Synopsis:
8234     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8235 
8236     Not Collective
8237 
8238     Input Parameters:
8239 +   x - matrix
8240 -   xx_v - the Fortran90 pointer to the array
8241 
8242     Output Parameter:
8243 .   ierr - error code
8244 
8245     Example of Usage:
8246 .vb
8247        PetscScalar, pointer xx_v(:)
8248        ....
8249        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8250        a = xx_v(3)
8251        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8252 .ve
8253 
8254     Level: advanced
8255 
8256 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8257 M*/
8258 
8259 /*@
8260     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8261                       as the original matrix.
8262 
8263     Collective
8264 
8265     Input Parameters:
8266 +   mat - the original matrix
8267 .   isrow - parallel `IS` containing the rows this processor should obtain
8268 .   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.
8269 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8270 
8271     Output Parameter:
8272 .   newmat - the new submatrix, of the same type as the original matrix
8273 
8274     Level: advanced
8275 
8276     Notes:
8277     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8278 
8279     Some matrix types place restrictions on the row and column indices, such
8280     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;
8281     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8282 
8283     The index sets may not have duplicate entries.
8284 
8285       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8286    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8287    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8288    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8289    you are finished using it.
8290 
8291     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8292     the input matrix.
8293 
8294     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8295 
8296    Example usage:
8297    Consider the following 8x8 matrix with 34 non-zero values, that is
8298    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8299    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8300    as follows
8301 .vb
8302             1  2  0  |  0  3  0  |  0  4
8303     Proc0   0  5  6  |  7  0  0  |  8  0
8304             9  0 10  | 11  0  0  | 12  0
8305     -------------------------------------
8306            13  0 14  | 15 16 17  |  0  0
8307     Proc1   0 18  0  | 19 20 21  |  0  0
8308             0  0  0  | 22 23  0  | 24  0
8309     -------------------------------------
8310     Proc2  25 26 27  |  0  0 28  | 29  0
8311            30  0  0  | 31 32 33  |  0 34
8312 .ve
8313 
8314     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8315 
8316 .vb
8317             2  0  |  0  3  0  |  0
8318     Proc0   5  6  |  7  0  0  |  8
8319     -------------------------------
8320     Proc1  18  0  | 19 20 21  |  0
8321     -------------------------------
8322     Proc2  26 27  |  0  0 28  | 29
8323             0  0  | 31 32 33  |  0
8324 .ve
8325 
8326 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8327 @*/
8328 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8329 {
8330   PetscMPIInt size;
8331   Mat        *local;
8332   IS          iscoltmp;
8333   PetscBool   flg;
8334 
8335   PetscFunctionBegin;
8336   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8337   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8338   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8339   PetscValidPointer(newmat, 5);
8340   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8341   PetscValidType(mat, 1);
8342   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8343   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8344 
8345   MatCheckPreallocated(mat, 1);
8346   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8347 
8348   if (!iscol || isrow == iscol) {
8349     PetscBool   stride;
8350     PetscMPIInt grabentirematrix = 0, grab;
8351     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8352     if (stride) {
8353       PetscInt first, step, n, rstart, rend;
8354       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8355       if (step == 1) {
8356         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8357         if (rstart == first) {
8358           PetscCall(ISGetLocalSize(isrow, &n));
8359           if (n == rend - rstart) grabentirematrix = 1;
8360         }
8361       }
8362     }
8363     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8364     if (grab) {
8365       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8366       if (cll == MAT_INITIAL_MATRIX) {
8367         *newmat = mat;
8368         PetscCall(PetscObjectReference((PetscObject)mat));
8369       }
8370       PetscFunctionReturn(PETSC_SUCCESS);
8371     }
8372   }
8373 
8374   if (!iscol) {
8375     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8376   } else {
8377     iscoltmp = iscol;
8378   }
8379 
8380   /* if original matrix is on just one processor then use submatrix generated */
8381   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8382     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8383     goto setproperties;
8384   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8385     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8386     *newmat = *local;
8387     PetscCall(PetscFree(local));
8388     goto setproperties;
8389   } else if (!mat->ops->createsubmatrix) {
8390     /* Create a new matrix type that implements the operation using the full matrix */
8391     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8392     switch (cll) {
8393     case MAT_INITIAL_MATRIX:
8394       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8395       break;
8396     case MAT_REUSE_MATRIX:
8397       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8398       break;
8399     default:
8400       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8401     }
8402     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8403     goto setproperties;
8404   }
8405 
8406   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8407   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8408   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8409 
8410 setproperties:
8411   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8412   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8413   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8414   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8415   PetscFunctionReturn(PETSC_SUCCESS);
8416 }
8417 
8418 /*@
8419    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8420 
8421    Not Collective
8422 
8423    Input Parameters:
8424 +  A - the matrix we wish to propagate options from
8425 -  B - the matrix we wish to propagate options to
8426 
8427    Level: beginner
8428 
8429    Note:
8430    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8431 
8432 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8433 @*/
8434 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8435 {
8436   PetscFunctionBegin;
8437   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8438   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8439   B->symmetry_eternal            = A->symmetry_eternal;
8440   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8441   B->symmetric                   = A->symmetric;
8442   B->structurally_symmetric      = A->structurally_symmetric;
8443   B->spd                         = A->spd;
8444   B->hermitian                   = A->hermitian;
8445   PetscFunctionReturn(PETSC_SUCCESS);
8446 }
8447 
8448 /*@
8449    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8450    used during the assembly process to store values that belong to
8451    other processors.
8452 
8453    Not Collective
8454 
8455    Input Parameters:
8456 +  mat   - the matrix
8457 .  size  - the initial size of the stash.
8458 -  bsize - the initial size of the block-stash(if used).
8459 
8460    Options Database Keys:
8461 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8462 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8463 
8464    Level: intermediate
8465 
8466    Notes:
8467      The block-stash is used for values set with `MatSetValuesBlocked()` while
8468      the stash is used for values set with `MatSetValues()`
8469 
8470      Run with the option -info and look for output of the form
8471      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8472      to determine the appropriate value, MM, to use for size and
8473      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8474      to determine the value, BMM to use for bsize
8475 
8476 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8477 @*/
8478 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8479 {
8480   PetscFunctionBegin;
8481   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8482   PetscValidType(mat, 1);
8483   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8484   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8485   PetscFunctionReturn(PETSC_SUCCESS);
8486 }
8487 
8488 /*@
8489    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8490      the matrix
8491 
8492    Neighbor-wise Collective
8493 
8494    Input Parameters:
8495 +  mat   - the matrix
8496 .  x - the vector to be multiplied by the interpolation operator
8497 -  y - the vector to be added to the result
8498 
8499    Output Parameter:
8500 .  w - the resulting vector
8501 
8502    Level: intermediate
8503 
8504    Notes:
8505     `w` may be the same vector as `y`.
8506 
8507     This allows one to use either the restriction or interpolation (its transpose)
8508     matrix to do the interpolation
8509 
8510 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8511 @*/
8512 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8513 {
8514   PetscInt M, N, Ny;
8515 
8516   PetscFunctionBegin;
8517   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8518   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8519   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8520   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8521   PetscCall(MatGetSize(A, &M, &N));
8522   PetscCall(VecGetSize(y, &Ny));
8523   if (M == Ny) {
8524     PetscCall(MatMultAdd(A, x, y, w));
8525   } else {
8526     PetscCall(MatMultTransposeAdd(A, x, y, w));
8527   }
8528   PetscFunctionReturn(PETSC_SUCCESS);
8529 }
8530 
8531 /*@
8532    MatInterpolate - y = A*x or A'*x depending on the shape of
8533      the matrix
8534 
8535    Neighbor-wise Collective
8536 
8537    Input Parameters:
8538 +  mat   - the matrix
8539 -  x - the vector to be interpolated
8540 
8541    Output Parameter:
8542 .  y - the resulting vector
8543 
8544    Level: intermediate
8545 
8546    Note:
8547     This allows one to use either the restriction or interpolation (its transpose)
8548     matrix to do the interpolation
8549 
8550 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8551 @*/
8552 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8553 {
8554   PetscInt M, N, Ny;
8555 
8556   PetscFunctionBegin;
8557   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8558   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8559   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8560   PetscCall(MatGetSize(A, &M, &N));
8561   PetscCall(VecGetSize(y, &Ny));
8562   if (M == Ny) {
8563     PetscCall(MatMult(A, x, y));
8564   } else {
8565     PetscCall(MatMultTranspose(A, x, y));
8566   }
8567   PetscFunctionReturn(PETSC_SUCCESS);
8568 }
8569 
8570 /*@
8571    MatRestrict - y = A*x or A'*x
8572 
8573    Neighbor-wise Collective
8574 
8575    Input Parameters:
8576 +  mat   - the matrix
8577 -  x - the vector to be restricted
8578 
8579    Output Parameter:
8580 .  y - the resulting vector
8581 
8582    Level: intermediate
8583 
8584    Note:
8585     This allows one to use either the restriction or interpolation (its transpose)
8586     matrix to do the restriction
8587 
8588 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8589 @*/
8590 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8591 {
8592   PetscInt M, N, Ny;
8593 
8594   PetscFunctionBegin;
8595   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8596   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8597   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8598   PetscCall(MatGetSize(A, &M, &N));
8599   PetscCall(VecGetSize(y, &Ny));
8600   if (M == Ny) {
8601     PetscCall(MatMult(A, x, y));
8602   } else {
8603     PetscCall(MatMultTranspose(A, x, y));
8604   }
8605   PetscFunctionReturn(PETSC_SUCCESS);
8606 }
8607 
8608 /*@
8609    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8610 
8611    Neighbor-wise Collective
8612 
8613    Input Parameters:
8614 +  mat   - the matrix
8615 .  x - the input dense matrix to be multiplied
8616 -  w - the input dense matrix to be added to the result
8617 
8618    Output Parameter:
8619 .  y - the output dense matrix
8620 
8621    Level: intermediate
8622 
8623    Note:
8624     This allows one to use either the restriction or interpolation (its transpose)
8625     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8626     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8627 
8628 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8629 @*/
8630 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8631 {
8632   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8633   PetscBool trans = PETSC_TRUE;
8634   MatReuse  reuse = MAT_INITIAL_MATRIX;
8635 
8636   PetscFunctionBegin;
8637   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8638   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8639   PetscValidType(x, 2);
8640   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8641   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8642   PetscCall(MatGetSize(A, &M, &N));
8643   PetscCall(MatGetSize(x, &Mx, &Nx));
8644   if (N == Mx) trans = PETSC_FALSE;
8645   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);
8646   Mo = trans ? N : M;
8647   if (*y) {
8648     PetscCall(MatGetSize(*y, &My, &Ny));
8649     if (Mo == My && Nx == Ny) {
8650       reuse = MAT_REUSE_MATRIX;
8651     } else {
8652       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);
8653       PetscCall(MatDestroy(y));
8654     }
8655   }
8656 
8657   if (w && *y == w) { /* this is to minimize changes in PCMG */
8658     PetscBool flg;
8659 
8660     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8661     if (w) {
8662       PetscInt My, Ny, Mw, Nw;
8663 
8664       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8665       PetscCall(MatGetSize(*y, &My, &Ny));
8666       PetscCall(MatGetSize(w, &Mw, &Nw));
8667       if (!flg || My != Mw || Ny != Nw) w = NULL;
8668     }
8669     if (!w) {
8670       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8671       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8672       PetscCall(PetscObjectDereference((PetscObject)w));
8673     } else {
8674       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8675     }
8676   }
8677   if (!trans) {
8678     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8679   } else {
8680     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8681   }
8682   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8683   PetscFunctionReturn(PETSC_SUCCESS);
8684 }
8685 
8686 /*@
8687    MatMatInterpolate - Y = A*X or A'*X
8688 
8689    Neighbor-wise Collective
8690 
8691    Input Parameters:
8692 +  mat   - the matrix
8693 -  x - the input dense matrix
8694 
8695    Output Parameter:
8696 .  y - the output dense matrix
8697 
8698    Level: intermediate
8699 
8700    Note:
8701     This allows one to use either the restriction or interpolation (its transpose)
8702     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8703     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8704 
8705 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8706 @*/
8707 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8708 {
8709   PetscFunctionBegin;
8710   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8711   PetscFunctionReturn(PETSC_SUCCESS);
8712 }
8713 
8714 /*@
8715    MatMatRestrict - Y = A*X or A'*X
8716 
8717    Neighbor-wise Collective
8718 
8719    Input Parameters:
8720 +  mat   - the matrix
8721 -  x - the input dense matrix
8722 
8723    Output Parameter:
8724 .  y - the output dense matrix
8725 
8726    Level: intermediate
8727 
8728    Note:
8729     This allows one to use either the restriction or interpolation (its transpose)
8730     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8731     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8732 
8733 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8734 @*/
8735 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8736 {
8737   PetscFunctionBegin;
8738   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8739   PetscFunctionReturn(PETSC_SUCCESS);
8740 }
8741 
8742 /*@
8743    MatGetNullSpace - retrieves the null space of a matrix.
8744 
8745    Logically Collective
8746 
8747    Input Parameters:
8748 +  mat - the matrix
8749 -  nullsp - the null space object
8750 
8751    Level: developer
8752 
8753 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8754 @*/
8755 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8756 {
8757   PetscFunctionBegin;
8758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8759   PetscValidPointer(nullsp, 2);
8760   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8761   PetscFunctionReturn(PETSC_SUCCESS);
8762 }
8763 
8764 /*@
8765    MatSetNullSpace - attaches a null space to a matrix.
8766 
8767    Logically Collective
8768 
8769    Input Parameters:
8770 +  mat - the matrix
8771 -  nullsp - the null space object
8772 
8773    Level: advanced
8774 
8775    Notes:
8776       This null space is used by the `KSP` linear solvers to solve singular systems.
8777 
8778       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`
8779 
8780       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
8781       to zero but the linear system will still be solved in a least squares sense.
8782 
8783       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8784    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).
8785    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
8786    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
8787    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).
8788    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8789 
8790     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8791     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8792     routine also automatically calls `MatSetTransposeNullSpace()`.
8793 
8794     The user should call `MatNullSpaceDestroy()`.
8795 
8796 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8797           `KSPSetPCSide()`
8798 @*/
8799 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8800 {
8801   PetscFunctionBegin;
8802   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8803   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8804   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8805   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8806   mat->nullsp = nullsp;
8807   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8808   PetscFunctionReturn(PETSC_SUCCESS);
8809 }
8810 
8811 /*@
8812    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8813 
8814    Logically Collective
8815 
8816    Input Parameters:
8817 +  mat - the matrix
8818 -  nullsp - the null space object
8819 
8820    Level: developer
8821 
8822 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8823 @*/
8824 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8825 {
8826   PetscFunctionBegin;
8827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8828   PetscValidType(mat, 1);
8829   PetscValidPointer(nullsp, 2);
8830   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8831   PetscFunctionReturn(PETSC_SUCCESS);
8832 }
8833 
8834 /*@
8835    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8836 
8837    Logically Collective
8838 
8839    Input Parameters:
8840 +  mat - the matrix
8841 -  nullsp - the null space object
8842 
8843    Level: advanced
8844 
8845    Notes:
8846    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8847 
8848    See `MatSetNullSpace()`
8849 
8850 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8851 @*/
8852 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8853 {
8854   PetscFunctionBegin;
8855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8856   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8857   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8858   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8859   mat->transnullsp = nullsp;
8860   PetscFunctionReturn(PETSC_SUCCESS);
8861 }
8862 
8863 /*@
8864    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8865         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8866 
8867    Logically Collective
8868 
8869    Input Parameters:
8870 +  mat - the matrix
8871 -  nullsp - the null space object
8872 
8873    Level: advanced
8874 
8875    Notes:
8876    Overwrites any previous near null space that may have been attached
8877 
8878    You can remove the null space by calling this routine with an nullsp of `NULL`
8879 
8880 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8881 @*/
8882 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8883 {
8884   PetscFunctionBegin;
8885   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8886   PetscValidType(mat, 1);
8887   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8888   MatCheckPreallocated(mat, 1);
8889   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8890   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8891   mat->nearnullsp = nullsp;
8892   PetscFunctionReturn(PETSC_SUCCESS);
8893 }
8894 
8895 /*@
8896    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8897 
8898    Not Collective
8899 
8900    Input Parameter:
8901 .  mat - the matrix
8902 
8903    Output Parameter:
8904 .  nullsp - the null space object, `NULL` if not set
8905 
8906    Level: advanced
8907 
8908 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8909 @*/
8910 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8911 {
8912   PetscFunctionBegin;
8913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8914   PetscValidType(mat, 1);
8915   PetscValidPointer(nullsp, 2);
8916   MatCheckPreallocated(mat, 1);
8917   *nullsp = mat->nearnullsp;
8918   PetscFunctionReturn(PETSC_SUCCESS);
8919 }
8920 
8921 /*@C
8922    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8923 
8924    Collective
8925 
8926    Input Parameters:
8927 +  mat - the matrix
8928 .  row - row/column permutation
8929 -  info - information on desired factorization process
8930 
8931    Level: developer
8932 
8933    Notes:
8934    Probably really in-place only when level of fill is zero, otherwise allocates
8935    new space to store factored matrix and deletes previous memory.
8936 
8937    Most users should employ the `KSP` interface for linear solvers
8938    instead of working directly with matrix algebra routines such as this.
8939    See, e.g., `KSPCreate()`.
8940 
8941    Developer Note:
8942    The Fortran interface is not autogenerated as the
8943    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8944 
8945 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8946 @*/
8947 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8948 {
8949   PetscFunctionBegin;
8950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8951   PetscValidType(mat, 1);
8952   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8953   PetscValidPointer(info, 3);
8954   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8955   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8956   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8957   MatCheckPreallocated(mat, 1);
8958   PetscUseTypeMethod(mat, iccfactor, row, info);
8959   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8960   PetscFunctionReturn(PETSC_SUCCESS);
8961 }
8962 
8963 /*@
8964    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8965          ghosted ones.
8966 
8967    Not Collective
8968 
8969    Input Parameters:
8970 +  mat - the matrix
8971 -  diag - the diagonal values, including ghost ones
8972 
8973    Level: developer
8974 
8975    Notes:
8976     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8977 
8978     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8979 
8980 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8981 @*/
8982 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8983 {
8984   PetscMPIInt size;
8985 
8986   PetscFunctionBegin;
8987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8988   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8989   PetscValidType(mat, 1);
8990 
8991   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8992   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8993   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8994   if (size == 1) {
8995     PetscInt n, m;
8996     PetscCall(VecGetSize(diag, &n));
8997     PetscCall(MatGetSize(mat, NULL, &m));
8998     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8999     PetscCall(MatDiagonalScale(mat, NULL, diag));
9000   } else {
9001     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9002   }
9003   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9004   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9005   PetscFunctionReturn(PETSC_SUCCESS);
9006 }
9007 
9008 /*@
9009    MatGetInertia - Gets the inertia from a factored matrix
9010 
9011    Collective
9012 
9013    Input Parameter:
9014 .  mat - the matrix
9015 
9016    Output Parameters:
9017 +   nneg - number of negative eigenvalues
9018 .   nzero - number of zero eigenvalues
9019 -   npos - number of positive eigenvalues
9020 
9021    Level: advanced
9022 
9023    Note:
9024     Matrix must have been factored by `MatCholeskyFactor()`
9025 
9026 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9027 @*/
9028 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9029 {
9030   PetscFunctionBegin;
9031   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9032   PetscValidType(mat, 1);
9033   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9034   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9035   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9036   PetscFunctionReturn(PETSC_SUCCESS);
9037 }
9038 
9039 /*@C
9040    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9041 
9042    Neighbor-wise Collective
9043 
9044    Input Parameters:
9045 +  mat - the factored matrix obtained with `MatGetFactor()`
9046 -  b - the right-hand-side vectors
9047 
9048    Output Parameter:
9049 .  x - the result vectors
9050 
9051    Level: developer
9052 
9053    Note:
9054    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9055    call `MatSolves`(A,x,x).
9056 
9057 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9058 @*/
9059 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9060 {
9061   PetscFunctionBegin;
9062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9063   PetscValidType(mat, 1);
9064   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9065   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9066   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9067 
9068   MatCheckPreallocated(mat, 1);
9069   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9070   PetscUseTypeMethod(mat, solves, b, x);
9071   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9072   PetscFunctionReturn(PETSC_SUCCESS);
9073 }
9074 
9075 /*@
9076    MatIsSymmetric - Test whether a matrix is symmetric
9077 
9078    Collective
9079 
9080    Input Parameters:
9081 +  A - the matrix to test
9082 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9083 
9084    Output Parameter:
9085 .  flg - the result
9086 
9087    Level: intermediate
9088 
9089    Notes:
9090     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9091 
9092     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9093 
9094     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9095     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9096 
9097 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9098           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9099 @*/
9100 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9101 {
9102   PetscFunctionBegin;
9103   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9104   PetscValidBoolPointer(flg, 3);
9105 
9106   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9107   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9108   else {
9109     PetscUseTypeMethod(A, issymmetric, tol, flg);
9110     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9111   }
9112   PetscFunctionReturn(PETSC_SUCCESS);
9113 }
9114 
9115 /*@
9116    MatIsHermitian - Test whether a matrix is Hermitian
9117 
9118    Collective
9119 
9120    Input Parameters:
9121 +  A - the matrix to test
9122 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9123 
9124    Output Parameter:
9125 .  flg - the result
9126 
9127    Level: intermediate
9128 
9129    Notes:
9130     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9131 
9132     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9133 
9134     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9135     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9136 
9137 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9138           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9139 @*/
9140 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9141 {
9142   PetscFunctionBegin;
9143   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9144   PetscValidBoolPointer(flg, 3);
9145 
9146   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9147   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9148   else {
9149     PetscUseTypeMethod(A, ishermitian, tol, flg);
9150     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9151   }
9152   PetscFunctionReturn(PETSC_SUCCESS);
9153 }
9154 
9155 /*@
9156    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9157 
9158    Not Collective
9159 
9160    Input Parameter:
9161 .  A - the matrix to check
9162 
9163    Output Parameters:
9164 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9165 -  flg - the result (only valid if set is `PETSC_TRUE`)
9166 
9167    Level: advanced
9168 
9169    Notes:
9170    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9171    if you want it explicitly checked
9172 
9173     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9174     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9175 
9176 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9177 @*/
9178 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9179 {
9180   PetscFunctionBegin;
9181   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9182   PetscValidBoolPointer(set, 2);
9183   PetscValidBoolPointer(flg, 3);
9184   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9185     *set = PETSC_TRUE;
9186     *flg = PetscBool3ToBool(A->symmetric);
9187   } else {
9188     *set = PETSC_FALSE;
9189   }
9190   PetscFunctionReturn(PETSC_SUCCESS);
9191 }
9192 
9193 /*@
9194    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9195 
9196    Not Collective
9197 
9198    Input Parameter:
9199 .  A - the matrix to check
9200 
9201    Output Parameters:
9202 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9203 -  flg - the result (only valid if set is `PETSC_TRUE`)
9204 
9205    Level: advanced
9206 
9207    Notes:
9208    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9209 
9210    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9211    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9212 
9213 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9214 @*/
9215 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9216 {
9217   PetscFunctionBegin;
9218   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9219   PetscValidBoolPointer(set, 2);
9220   PetscValidBoolPointer(flg, 3);
9221   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9222     *set = PETSC_TRUE;
9223     *flg = PetscBool3ToBool(A->spd);
9224   } else {
9225     *set = PETSC_FALSE;
9226   }
9227   PetscFunctionReturn(PETSC_SUCCESS);
9228 }
9229 
9230 /*@
9231    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9232 
9233    Not Collective
9234 
9235    Input Parameter:
9236 .  A - the matrix to check
9237 
9238    Output Parameters:
9239 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9240 -  flg - the result (only valid if set is `PETSC_TRUE`)
9241 
9242    Level: advanced
9243 
9244    Notes:
9245    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9246    if you want it explicitly checked
9247 
9248    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9249    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9250 
9251 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9252 @*/
9253 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9254 {
9255   PetscFunctionBegin;
9256   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9257   PetscValidBoolPointer(set, 2);
9258   PetscValidBoolPointer(flg, 3);
9259   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9260     *set = PETSC_TRUE;
9261     *flg = PetscBool3ToBool(A->hermitian);
9262   } else {
9263     *set = PETSC_FALSE;
9264   }
9265   PetscFunctionReturn(PETSC_SUCCESS);
9266 }
9267 
9268 /*@
9269    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9270 
9271    Collective
9272 
9273    Input Parameter:
9274 .  A - the matrix to test
9275 
9276    Output Parameter:
9277 .  flg - the result
9278 
9279    Level: intermediate
9280 
9281    Notes:
9282    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9283 
9284    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
9285    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9286 
9287 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9288 @*/
9289 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9290 {
9291   PetscFunctionBegin;
9292   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9293   PetscValidBoolPointer(flg, 2);
9294   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9295     *flg = PetscBool3ToBool(A->structurally_symmetric);
9296   } else {
9297     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9298     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9299   }
9300   PetscFunctionReturn(PETSC_SUCCESS);
9301 }
9302 
9303 /*@
9304    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9305 
9306    Not Collective
9307 
9308    Input Parameter:
9309 .  A - the matrix to check
9310 
9311    Output Parameters:
9312 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9313 -  flg - the result (only valid if set is PETSC_TRUE)
9314 
9315    Level: advanced
9316 
9317    Notes:
9318    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
9319    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9320 
9321    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9322 
9323 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9324 @*/
9325 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9326 {
9327   PetscFunctionBegin;
9328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9329   PetscValidBoolPointer(set, 2);
9330   PetscValidBoolPointer(flg, 3);
9331   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9332     *set = PETSC_TRUE;
9333     *flg = PetscBool3ToBool(A->structurally_symmetric);
9334   } else {
9335     *set = PETSC_FALSE;
9336   }
9337   PetscFunctionReturn(PETSC_SUCCESS);
9338 }
9339 
9340 /*@
9341    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9342        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9343 
9344     Not Collective
9345 
9346    Input Parameter:
9347 .   mat - the matrix
9348 
9349    Output Parameters:
9350 +   nstash   - the size of the stash
9351 .   reallocs - the number of additional mallocs incurred.
9352 .   bnstash   - the size of the block stash
9353 -   breallocs - the number of additional mallocs incurred.in the block stash
9354 
9355    Level: advanced
9356 
9357 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9358 @*/
9359 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9360 {
9361   PetscFunctionBegin;
9362   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9363   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9364   PetscFunctionReturn(PETSC_SUCCESS);
9365 }
9366 
9367 /*@C
9368    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9369    parallel layout, `PetscLayout` for rows and columns
9370 
9371    Collective
9372 
9373    Input Parameter:
9374 .  mat - the matrix
9375 
9376    Output Parameters:
9377 +   right - (optional) vector that the matrix can be multiplied against
9378 -   left - (optional) vector that the matrix vector product can be stored in
9379 
9380   Level: advanced
9381 
9382    Notes:
9383     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()`.
9384 
9385     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9386 
9387 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9388 @*/
9389 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9390 {
9391   PetscFunctionBegin;
9392   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9393   PetscValidType(mat, 1);
9394   if (mat->ops->getvecs) {
9395     PetscUseTypeMethod(mat, getvecs, right, left);
9396   } else {
9397     PetscInt rbs, cbs;
9398     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9399     if (right) {
9400       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9401       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9402       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9403       PetscCall(VecSetBlockSize(*right, cbs));
9404       PetscCall(VecSetType(*right, mat->defaultvectype));
9405 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9406       if (mat->boundtocpu && mat->bindingpropagates) {
9407         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9408         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9409       }
9410 #endif
9411       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9412     }
9413     if (left) {
9414       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9415       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9416       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9417       PetscCall(VecSetBlockSize(*left, rbs));
9418       PetscCall(VecSetType(*left, mat->defaultvectype));
9419 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9420       if (mat->boundtocpu && mat->bindingpropagates) {
9421         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9422         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9423       }
9424 #endif
9425       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9426     }
9427   }
9428   PetscFunctionReturn(PETSC_SUCCESS);
9429 }
9430 
9431 /*@C
9432    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9433      with default values.
9434 
9435    Not Collective
9436 
9437    Input Parameter:
9438 .    info - the `MatFactorInfo` data structure
9439 
9440    Level: developer
9441 
9442    Notes:
9443     The solvers are generally used through the `KSP` and `PC` objects, for example
9444           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9445 
9446     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9447 
9448    Developer Note:
9449    The Fortran interface is not autogenerated as the
9450    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9451 
9452 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9453 @*/
9454 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9455 {
9456   PetscFunctionBegin;
9457   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9458   PetscFunctionReturn(PETSC_SUCCESS);
9459 }
9460 
9461 /*@
9462    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9463 
9464    Collective
9465 
9466    Input Parameters:
9467 +  mat - the factored matrix
9468 -  is - the index set defining the Schur indices (0-based)
9469 
9470    Level: advanced
9471 
9472    Notes:
9473     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9474 
9475    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9476 
9477    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9478 
9479 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9480           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9481 @*/
9482 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9483 {
9484   PetscErrorCode (*f)(Mat, IS);
9485 
9486   PetscFunctionBegin;
9487   PetscValidType(mat, 1);
9488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9489   PetscValidType(is, 2);
9490   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9491   PetscCheckSameComm(mat, 1, is, 2);
9492   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9493   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9494   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9495   PetscCall(MatDestroy(&mat->schur));
9496   PetscCall((*f)(mat, is));
9497   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9498   PetscFunctionReturn(PETSC_SUCCESS);
9499 }
9500 
9501 /*@
9502   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9503 
9504    Logically Collective
9505 
9506    Input Parameters:
9507 +  F - the factored matrix obtained by calling `MatGetFactor()`
9508 .  S - location where to return the Schur complement, can be `NULL`
9509 -  status - the status of the Schur complement matrix, can be `NULL`
9510 
9511    Level: advanced
9512 
9513    Notes:
9514    You must call `MatFactorSetSchurIS()` before calling this routine.
9515 
9516    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9517 
9518    The routine provides a copy of the Schur matrix stored within the solver data structures.
9519    The caller must destroy the object when it is no longer needed.
9520    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9521 
9522    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)
9523 
9524    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9525 
9526    Developer Note:
9527     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9528    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9529 
9530 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9531 @*/
9532 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9533 {
9534   PetscFunctionBegin;
9535   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9536   if (S) PetscValidPointer(S, 2);
9537   if (status) PetscValidPointer(status, 3);
9538   if (S) {
9539     PetscErrorCode (*f)(Mat, Mat *);
9540 
9541     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9542     if (f) {
9543       PetscCall((*f)(F, S));
9544     } else {
9545       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9546     }
9547   }
9548   if (status) *status = F->schur_status;
9549   PetscFunctionReturn(PETSC_SUCCESS);
9550 }
9551 
9552 /*@
9553   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9554 
9555    Logically Collective
9556 
9557    Input Parameters:
9558 +  F - the factored matrix obtained by calling `MatGetFactor()`
9559 .  *S - location where to return the Schur complement, can be `NULL`
9560 -  status - the status of the Schur complement matrix, can be `NULL`
9561 
9562    Level: advanced
9563 
9564    Notes:
9565    You must call `MatFactorSetSchurIS()` before calling this routine.
9566 
9567    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9568 
9569    The routine returns a the Schur Complement stored within the data structures of the solver.
9570 
9571    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9572 
9573    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9574 
9575    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9576 
9577    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9578 
9579 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9580 @*/
9581 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9582 {
9583   PetscFunctionBegin;
9584   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9585   if (S) PetscValidPointer(S, 2);
9586   if (status) PetscValidPointer(status, 3);
9587   if (S) *S = F->schur;
9588   if (status) *status = F->schur_status;
9589   PetscFunctionReturn(PETSC_SUCCESS);
9590 }
9591 
9592 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9593 {
9594   Mat S = F->schur;
9595 
9596   PetscFunctionBegin;
9597   switch (F->schur_status) {
9598   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9599   case MAT_FACTOR_SCHUR_INVERTED:
9600     if (S) {
9601       S->ops->solve             = NULL;
9602       S->ops->matsolve          = NULL;
9603       S->ops->solvetranspose    = NULL;
9604       S->ops->matsolvetranspose = NULL;
9605       S->ops->solveadd          = NULL;
9606       S->ops->solvetransposeadd = NULL;
9607       S->factortype             = MAT_FACTOR_NONE;
9608       PetscCall(PetscFree(S->solvertype));
9609     }
9610   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9611     break;
9612   default:
9613     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9614   }
9615   PetscFunctionReturn(PETSC_SUCCESS);
9616 }
9617 
9618 /*@
9619   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9620 
9621    Logically Collective
9622 
9623    Input Parameters:
9624 +  F - the factored matrix obtained by calling `MatGetFactor()`
9625 .  *S - location where the Schur complement is stored
9626 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9627 
9628    Level: advanced
9629 
9630 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9631 @*/
9632 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9633 {
9634   PetscFunctionBegin;
9635   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9636   if (S) {
9637     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9638     *S = NULL;
9639   }
9640   F->schur_status = status;
9641   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9642   PetscFunctionReturn(PETSC_SUCCESS);
9643 }
9644 
9645 /*@
9646   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9647 
9648    Logically Collective
9649 
9650    Input Parameters:
9651 +  F - the factored matrix obtained by calling `MatGetFactor()`
9652 .  rhs - location where the right hand side of the Schur complement system is stored
9653 -  sol - location where the solution of the Schur complement system has to be returned
9654 
9655    Level: advanced
9656 
9657    Notes:
9658    The sizes of the vectors should match the size of the Schur complement
9659 
9660    Must be called after `MatFactorSetSchurIS()`
9661 
9662 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9663 @*/
9664 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9665 {
9666   PetscFunctionBegin;
9667   PetscValidType(F, 1);
9668   PetscValidType(rhs, 2);
9669   PetscValidType(sol, 3);
9670   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9671   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9672   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9673   PetscCheckSameComm(F, 1, rhs, 2);
9674   PetscCheckSameComm(F, 1, sol, 3);
9675   PetscCall(MatFactorFactorizeSchurComplement(F));
9676   switch (F->schur_status) {
9677   case MAT_FACTOR_SCHUR_FACTORED:
9678     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9679     break;
9680   case MAT_FACTOR_SCHUR_INVERTED:
9681     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9682     break;
9683   default:
9684     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9685   }
9686   PetscFunctionReturn(PETSC_SUCCESS);
9687 }
9688 
9689 /*@
9690   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9691 
9692    Logically Collective
9693 
9694    Input Parameters:
9695 +  F - the factored matrix obtained by calling `MatGetFactor()`
9696 .  rhs - location where the right hand side of the Schur complement system is stored
9697 -  sol - location where the solution of the Schur complement system has to be returned
9698 
9699    Level: advanced
9700 
9701    Notes:
9702    The sizes of the vectors should match the size of the Schur complement
9703 
9704    Must be called after `MatFactorSetSchurIS()`
9705 
9706 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9707 @*/
9708 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9709 {
9710   PetscFunctionBegin;
9711   PetscValidType(F, 1);
9712   PetscValidType(rhs, 2);
9713   PetscValidType(sol, 3);
9714   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9715   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9716   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9717   PetscCheckSameComm(F, 1, rhs, 2);
9718   PetscCheckSameComm(F, 1, sol, 3);
9719   PetscCall(MatFactorFactorizeSchurComplement(F));
9720   switch (F->schur_status) {
9721   case MAT_FACTOR_SCHUR_FACTORED:
9722     PetscCall(MatSolve(F->schur, rhs, sol));
9723     break;
9724   case MAT_FACTOR_SCHUR_INVERTED:
9725     PetscCall(MatMult(F->schur, rhs, sol));
9726     break;
9727   default:
9728     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9729   }
9730   PetscFunctionReturn(PETSC_SUCCESS);
9731 }
9732 
9733 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9734 #if PetscDefined(HAVE_CUDA)
9735 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9736 #endif
9737 
9738 /* Schur status updated in the interface */
9739 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9740 {
9741   Mat S = F->schur;
9742 
9743   PetscFunctionBegin;
9744   if (S) {
9745     PetscMPIInt size;
9746     PetscBool   isdense, isdensecuda;
9747 
9748     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9749     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9750     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9751     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9752     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9753     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9754     if (isdense) {
9755       PetscCall(MatSeqDenseInvertFactors_Private(S));
9756     } else if (isdensecuda) {
9757 #if defined(PETSC_HAVE_CUDA)
9758       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9759 #endif
9760     }
9761     // HIP??????????????
9762     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9763   }
9764   PetscFunctionReturn(PETSC_SUCCESS);
9765 }
9766 
9767 /*@
9768   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9769 
9770    Logically Collective
9771 
9772    Input Parameter:
9773 .  F - the factored matrix obtained by calling `MatGetFactor()`
9774 
9775    Level: advanced
9776 
9777    Notes:
9778     Must be called after `MatFactorSetSchurIS()`.
9779 
9780    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9781 
9782 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9783 @*/
9784 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9785 {
9786   PetscFunctionBegin;
9787   PetscValidType(F, 1);
9788   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9789   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9790   PetscCall(MatFactorFactorizeSchurComplement(F));
9791   PetscCall(MatFactorInvertSchurComplement_Private(F));
9792   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9793   PetscFunctionReturn(PETSC_SUCCESS);
9794 }
9795 
9796 /*@
9797   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9798 
9799    Logically Collective
9800 
9801    Input Parameter:
9802 .  F - the factored matrix obtained by calling `MatGetFactor()`
9803 
9804    Level: advanced
9805 
9806    Note:
9807     Must be called after `MatFactorSetSchurIS()`
9808 
9809 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9810 @*/
9811 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9812 {
9813   MatFactorInfo info;
9814 
9815   PetscFunctionBegin;
9816   PetscValidType(F, 1);
9817   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9818   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9819   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9820   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9821   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9822     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9823   } else {
9824     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9825   }
9826   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9827   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9828   PetscFunctionReturn(PETSC_SUCCESS);
9829 }
9830 
9831 /*@
9832    MatPtAP - Creates the matrix product C = P^T * A * P
9833 
9834    Neighbor-wise Collective
9835 
9836    Input Parameters:
9837 +  A - the matrix
9838 .  P - the projection matrix
9839 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9840 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9841           if the result is a dense matrix this is irrelevant
9842 
9843    Output Parameter:
9844 .  C - the product matrix
9845 
9846    Level: intermediate
9847 
9848    Notes:
9849    C will be created and must be destroyed by the user with `MatDestroy()`.
9850 
9851    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9852 
9853    Developer Note:
9854    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9855 
9856 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9857 @*/
9858 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9859 {
9860   PetscFunctionBegin;
9861   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9862   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9863 
9864   if (scall == MAT_INITIAL_MATRIX) {
9865     PetscCall(MatProductCreate(A, P, NULL, C));
9866     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9867     PetscCall(MatProductSetAlgorithm(*C, "default"));
9868     PetscCall(MatProductSetFill(*C, fill));
9869 
9870     (*C)->product->api_user = PETSC_TRUE;
9871     PetscCall(MatProductSetFromOptions(*C));
9872     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);
9873     PetscCall(MatProductSymbolic(*C));
9874   } else { /* scall == MAT_REUSE_MATRIX */
9875     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9876   }
9877 
9878   PetscCall(MatProductNumeric(*C));
9879   (*C)->symmetric = A->symmetric;
9880   (*C)->spd       = A->spd;
9881   PetscFunctionReturn(PETSC_SUCCESS);
9882 }
9883 
9884 /*@
9885    MatRARt - Creates the matrix product C = R * A * R^T
9886 
9887    Neighbor-wise Collective
9888 
9889    Input Parameters:
9890 +  A - the matrix
9891 .  R - the projection matrix
9892 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9893 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9894           if the result is a dense matrix this is irrelevant
9895 
9896    Output Parameter:
9897 .  C - the product matrix
9898 
9899    Level: intermediate
9900 
9901    Notes:
9902    C will be created and must be destroyed by the user with `MatDestroy()`.
9903 
9904    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9905 
9906    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9907    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9908    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9909    We recommend using MatPtAP().
9910 
9911 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9912 @*/
9913 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9914 {
9915   PetscFunctionBegin;
9916   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9917   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9918 
9919   if (scall == MAT_INITIAL_MATRIX) {
9920     PetscCall(MatProductCreate(A, R, NULL, C));
9921     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9922     PetscCall(MatProductSetAlgorithm(*C, "default"));
9923     PetscCall(MatProductSetFill(*C, fill));
9924 
9925     (*C)->product->api_user = PETSC_TRUE;
9926     PetscCall(MatProductSetFromOptions(*C));
9927     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);
9928     PetscCall(MatProductSymbolic(*C));
9929   } else { /* scall == MAT_REUSE_MATRIX */
9930     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9931   }
9932 
9933   PetscCall(MatProductNumeric(*C));
9934   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9935   PetscFunctionReturn(PETSC_SUCCESS);
9936 }
9937 
9938 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9939 {
9940   PetscFunctionBegin;
9941   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9942 
9943   if (scall == MAT_INITIAL_MATRIX) {
9944     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9945     PetscCall(MatProductCreate(A, B, NULL, C));
9946     PetscCall(MatProductSetType(*C, ptype));
9947     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9948     PetscCall(MatProductSetFill(*C, fill));
9949 
9950     (*C)->product->api_user = PETSC_TRUE;
9951     PetscCall(MatProductSetFromOptions(*C));
9952     PetscCall(MatProductSymbolic(*C));
9953   } else { /* scall == MAT_REUSE_MATRIX */
9954     Mat_Product *product = (*C)->product;
9955     PetscBool    isdense;
9956 
9957     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9958     if (isdense && product && product->type != ptype) {
9959       PetscCall(MatProductClear(*C));
9960       product = NULL;
9961     }
9962     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9963     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9964       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9965       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9966       product           = (*C)->product;
9967       product->fill     = fill;
9968       product->api_user = PETSC_TRUE;
9969       product->clear    = PETSC_TRUE;
9970 
9971       PetscCall(MatProductSetType(*C, ptype));
9972       PetscCall(MatProductSetFromOptions(*C));
9973       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);
9974       PetscCall(MatProductSymbolic(*C));
9975     } else { /* user may change input matrices A or B when REUSE */
9976       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9977     }
9978   }
9979   PetscCall(MatProductNumeric(*C));
9980   PetscFunctionReturn(PETSC_SUCCESS);
9981 }
9982 
9983 /*@
9984    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9985 
9986    Neighbor-wise Collective
9987 
9988    Input Parameters:
9989 +  A - the left matrix
9990 .  B - the right matrix
9991 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9992 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9993           if the result is a dense matrix this is irrelevant
9994 
9995    Output Parameter:
9996 .  C - the product matrix
9997 
9998    Notes:
9999    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10000 
10001    `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
10002    call to this function with `MAT_INITIAL_MATRIX`.
10003 
10004    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10005 
10006    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`,
10007    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10008 
10009    Example of Usage:
10010 .vb
10011      MatProductCreate(A,B,NULL,&C);
10012      MatProductSetType(C,MATPRODUCT_AB);
10013      MatProductSymbolic(C);
10014      MatProductNumeric(C); // compute C=A * B
10015      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10016      MatProductNumeric(C);
10017      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10018      MatProductNumeric(C);
10019 .ve
10020 
10021    Level: intermediate
10022 
10023 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10024 @*/
10025 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10026 {
10027   PetscFunctionBegin;
10028   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10029   PetscFunctionReturn(PETSC_SUCCESS);
10030 }
10031 
10032 /*@
10033    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10034 
10035    Neighbor-wise Collective
10036 
10037    Input Parameters:
10038 +  A - the left matrix
10039 .  B - the right matrix
10040 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10041 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10042 
10043    Output Parameter:
10044 .  C - the product matrix
10045 
10046    Level: intermediate
10047 
10048    Notes:
10049    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10050 
10051    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10052 
10053    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10054    actually needed.
10055 
10056    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10057    and for pairs of `MATMPIDENSE` matrices.
10058 
10059    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10060 
10061    Options Database Keys:
10062 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10063               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10064               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10065 
10066 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10067 @*/
10068 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10069 {
10070   PetscFunctionBegin;
10071   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10072   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10073   PetscFunctionReturn(PETSC_SUCCESS);
10074 }
10075 
10076 /*@
10077    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10078 
10079    Neighbor-wise Collective
10080 
10081    Input Parameters:
10082 +  A - the left matrix
10083 .  B - the right matrix
10084 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10085 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10086 
10087    Output Parameter:
10088 .  C - the product matrix
10089 
10090    Level: intermediate
10091 
10092    Notes:
10093    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10094 
10095    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10096 
10097    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10098 
10099    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10100    actually needed.
10101 
10102    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10103    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10104 
10105 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10106 @*/
10107 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10108 {
10109   PetscFunctionBegin;
10110   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10111   PetscFunctionReturn(PETSC_SUCCESS);
10112 }
10113 
10114 /*@
10115    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10116 
10117    Neighbor-wise Collective
10118 
10119    Input Parameters:
10120 +  A - the left matrix
10121 .  B - the middle matrix
10122 .  C - the right matrix
10123 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10124 -  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
10125           if the result is a dense matrix this is irrelevant
10126 
10127    Output Parameter:
10128 .  D - the product matrix
10129 
10130    Level: intermediate
10131 
10132    Notes:
10133    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10134 
10135    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10136 
10137    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10138 
10139    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10140    actually needed.
10141 
10142    If you have many matrices with the same non-zero structure to multiply, you
10143    should use `MAT_REUSE_MATRIX` in all calls but the first
10144 
10145 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10146 @*/
10147 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10148 {
10149   PetscFunctionBegin;
10150   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10151   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10152 
10153   if (scall == MAT_INITIAL_MATRIX) {
10154     PetscCall(MatProductCreate(A, B, C, D));
10155     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10156     PetscCall(MatProductSetAlgorithm(*D, "default"));
10157     PetscCall(MatProductSetFill(*D, fill));
10158 
10159     (*D)->product->api_user = PETSC_TRUE;
10160     PetscCall(MatProductSetFromOptions(*D));
10161     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,
10162                ((PetscObject)C)->type_name);
10163     PetscCall(MatProductSymbolic(*D));
10164   } else { /* user may change input matrices when REUSE */
10165     PetscCall(MatProductReplaceMats(A, B, C, *D));
10166   }
10167   PetscCall(MatProductNumeric(*D));
10168   PetscFunctionReturn(PETSC_SUCCESS);
10169 }
10170 
10171 /*@
10172    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10173 
10174    Collective
10175 
10176    Input Parameters:
10177 +  mat - the matrix
10178 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10179 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10180 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10181 
10182    Output Parameter:
10183 .  matredundant - redundant matrix
10184 
10185    Level: advanced
10186 
10187    Notes:
10188    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10189    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10190 
10191    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10192    calling it.
10193 
10194    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10195 
10196 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10197 @*/
10198 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10199 {
10200   MPI_Comm       comm;
10201   PetscMPIInt    size;
10202   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10203   Mat_Redundant *redund     = NULL;
10204   PetscSubcomm   psubcomm   = NULL;
10205   MPI_Comm       subcomm_in = subcomm;
10206   Mat           *matseq;
10207   IS             isrow, iscol;
10208   PetscBool      newsubcomm = PETSC_FALSE;
10209 
10210   PetscFunctionBegin;
10211   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10212   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10213     PetscValidPointer(*matredundant, 5);
10214     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10215   }
10216 
10217   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10218   if (size == 1 || nsubcomm == 1) {
10219     if (reuse == MAT_INITIAL_MATRIX) {
10220       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10221     } else {
10222       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");
10223       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10224     }
10225     PetscFunctionReturn(PETSC_SUCCESS);
10226   }
10227 
10228   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10229   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10230   MatCheckPreallocated(mat, 1);
10231 
10232   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10233   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10234     /* create psubcomm, then get subcomm */
10235     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10236     PetscCallMPI(MPI_Comm_size(comm, &size));
10237     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10238 
10239     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10240     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10241     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10242     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10243     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10244     newsubcomm = PETSC_TRUE;
10245     PetscCall(PetscSubcommDestroy(&psubcomm));
10246   }
10247 
10248   /* get isrow, iscol and a local sequential matrix matseq[0] */
10249   if (reuse == MAT_INITIAL_MATRIX) {
10250     mloc_sub = PETSC_DECIDE;
10251     nloc_sub = PETSC_DECIDE;
10252     if (bs < 1) {
10253       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10254       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10255     } else {
10256       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10257       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10258     }
10259     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10260     rstart = rend - mloc_sub;
10261     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10262     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10263   } else { /* reuse == MAT_REUSE_MATRIX */
10264     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");
10265     /* retrieve subcomm */
10266     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10267     redund = (*matredundant)->redundant;
10268     isrow  = redund->isrow;
10269     iscol  = redund->iscol;
10270     matseq = redund->matseq;
10271   }
10272   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10273 
10274   /* get matredundant over subcomm */
10275   if (reuse == MAT_INITIAL_MATRIX) {
10276     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10277 
10278     /* create a supporting struct and attach it to C for reuse */
10279     PetscCall(PetscNew(&redund));
10280     (*matredundant)->redundant = redund;
10281     redund->isrow              = isrow;
10282     redund->iscol              = iscol;
10283     redund->matseq             = matseq;
10284     if (newsubcomm) {
10285       redund->subcomm = subcomm;
10286     } else {
10287       redund->subcomm = MPI_COMM_NULL;
10288     }
10289   } else {
10290     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10291   }
10292 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10293   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10294     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10295     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10296   }
10297 #endif
10298   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10299   PetscFunctionReturn(PETSC_SUCCESS);
10300 }
10301 
10302 /*@C
10303    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10304    a given `Mat`. Each submatrix can span multiple procs.
10305 
10306    Collective
10307 
10308    Input Parameters:
10309 +  mat - the matrix
10310 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10311 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10312 
10313    Output Parameter:
10314 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10315 
10316   Level: advanced
10317 
10318   Notes:
10319   The submatrix partition across processors is dictated by `subComm` a
10320   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10321   is not restricted to be grouped with consecutive original ranks.
10322 
10323   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10324   map directly to the layout of the original matrix [wrt the local
10325   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10326   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10327   the `subMat`. However the offDiagMat looses some columns - and this is
10328   reconstructed with `MatSetValues()`
10329 
10330   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10331 
10332 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10333 @*/
10334 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10335 {
10336   PetscMPIInt commsize, subCommSize;
10337 
10338   PetscFunctionBegin;
10339   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10340   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10341   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10342 
10343   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");
10344   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10345   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10346   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10347   PetscFunctionReturn(PETSC_SUCCESS);
10348 }
10349 
10350 /*@
10351    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10352 
10353    Not Collective
10354 
10355    Input Parameters:
10356 +  mat - matrix to extract local submatrix from
10357 .  isrow - local row indices for submatrix
10358 -  iscol - local column indices for submatrix
10359 
10360    Output Parameter:
10361 .  submat - the submatrix
10362 
10363    Level: intermediate
10364 
10365    Notes:
10366    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10367 
10368    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10369    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10370 
10371    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10372    `MatSetValuesBlockedLocal()` will also be implemented.
10373 
10374    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10375    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10376 
10377 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10378 @*/
10379 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10380 {
10381   PetscFunctionBegin;
10382   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10383   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10384   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10385   PetscCheckSameComm(isrow, 2, iscol, 3);
10386   PetscValidPointer(submat, 4);
10387   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10388 
10389   if (mat->ops->getlocalsubmatrix) {
10390     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10391   } else {
10392     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10393   }
10394   PetscFunctionReturn(PETSC_SUCCESS);
10395 }
10396 
10397 /*@
10398    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10399 
10400    Not Collective
10401 
10402    Input Parameters:
10403 +  mat - matrix to extract local submatrix from
10404 .  isrow - local row indices for submatrix
10405 .  iscol - local column indices for submatrix
10406 -  submat - the submatrix
10407 
10408    Level: intermediate
10409 
10410 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10411 @*/
10412 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10413 {
10414   PetscFunctionBegin;
10415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10416   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10417   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10418   PetscCheckSameComm(isrow, 2, iscol, 3);
10419   PetscValidPointer(submat, 4);
10420   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10421 
10422   if (mat->ops->restorelocalsubmatrix) {
10423     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10424   } else {
10425     PetscCall(MatDestroy(submat));
10426   }
10427   *submat = NULL;
10428   PetscFunctionReturn(PETSC_SUCCESS);
10429 }
10430 
10431 /*@
10432    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10433 
10434    Collective
10435 
10436    Input Parameter:
10437 .  mat - the matrix
10438 
10439    Output Parameter:
10440 .  is - if any rows have zero diagonals this contains the list of them
10441 
10442    Level: developer
10443 
10444 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10445 @*/
10446 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10447 {
10448   PetscFunctionBegin;
10449   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10450   PetscValidType(mat, 1);
10451   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10452   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10453 
10454   if (!mat->ops->findzerodiagonals) {
10455     Vec                diag;
10456     const PetscScalar *a;
10457     PetscInt          *rows;
10458     PetscInt           rStart, rEnd, r, nrow = 0;
10459 
10460     PetscCall(MatCreateVecs(mat, &diag, NULL));
10461     PetscCall(MatGetDiagonal(mat, diag));
10462     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10463     PetscCall(VecGetArrayRead(diag, &a));
10464     for (r = 0; r < rEnd - rStart; ++r)
10465       if (a[r] == 0.0) ++nrow;
10466     PetscCall(PetscMalloc1(nrow, &rows));
10467     nrow = 0;
10468     for (r = 0; r < rEnd - rStart; ++r)
10469       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10470     PetscCall(VecRestoreArrayRead(diag, &a));
10471     PetscCall(VecDestroy(&diag));
10472     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10473   } else {
10474     PetscUseTypeMethod(mat, findzerodiagonals, is);
10475   }
10476   PetscFunctionReturn(PETSC_SUCCESS);
10477 }
10478 
10479 /*@
10480    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10481 
10482    Collective
10483 
10484    Input Parameter:
10485 .  mat - the matrix
10486 
10487    Output Parameter:
10488 .  is - contains the list of rows with off block diagonal entries
10489 
10490    Level: developer
10491 
10492 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10493 @*/
10494 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10495 {
10496   PetscFunctionBegin;
10497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10498   PetscValidType(mat, 1);
10499   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10500   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10501 
10502   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10503   PetscFunctionReturn(PETSC_SUCCESS);
10504 }
10505 
10506 /*@C
10507   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10508 
10509   Collective; No Fortran Support
10510 
10511   Input Parameter:
10512 . mat - the matrix
10513 
10514   Output Parameter:
10515 . values - the block inverses in column major order (FORTRAN-like)
10516 
10517   Level: advanced
10518 
10519    Notes:
10520    The size of the blocks is determined by the block size of the matrix.
10521 
10522    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10523 
10524    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10525 
10526 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10527 @*/
10528 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10529 {
10530   PetscFunctionBegin;
10531   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10532   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10533   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10534   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10535   PetscFunctionReturn(PETSC_SUCCESS);
10536 }
10537 
10538 /*@C
10539   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10540 
10541   Collective; No Fortran Support
10542 
10543   Input Parameters:
10544 + mat - the matrix
10545 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10546 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10547 
10548   Output Parameter:
10549 . values - the block inverses in column major order (FORTRAN-like)
10550 
10551   Level: advanced
10552 
10553   Notes:
10554   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10555 
10556   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10557 
10558 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10559 @*/
10560 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10561 {
10562   PetscFunctionBegin;
10563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10564   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10565   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10566   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10567   PetscFunctionReturn(PETSC_SUCCESS);
10568 }
10569 
10570 /*@
10571   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10572 
10573   Collective
10574 
10575   Input Parameters:
10576 + A - the matrix
10577 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10578 
10579   Level: advanced
10580 
10581   Note:
10582   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10583 
10584 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10585 @*/
10586 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10587 {
10588   const PetscScalar *vals;
10589   PetscInt          *dnnz;
10590   PetscInt           m, rstart, rend, bs, i, j;
10591 
10592   PetscFunctionBegin;
10593   PetscCall(MatInvertBlockDiagonal(A, &vals));
10594   PetscCall(MatGetBlockSize(A, &bs));
10595   PetscCall(MatGetLocalSize(A, &m, NULL));
10596   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10597   PetscCall(PetscMalloc1(m / bs, &dnnz));
10598   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10599   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10600   PetscCall(PetscFree(dnnz));
10601   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10602   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10603   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10604   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10605   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10606   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10607   PetscFunctionReturn(PETSC_SUCCESS);
10608 }
10609 
10610 /*@C
10611     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10612     via `MatTransposeColoringCreate()`.
10613 
10614     Collective
10615 
10616     Input Parameter:
10617 .   c - coloring context
10618 
10619     Level: intermediate
10620 
10621 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10622 @*/
10623 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10624 {
10625   MatTransposeColoring matcolor = *c;
10626 
10627   PetscFunctionBegin;
10628   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10629   if (--((PetscObject)matcolor)->refct > 0) {
10630     matcolor = NULL;
10631     PetscFunctionReturn(PETSC_SUCCESS);
10632   }
10633 
10634   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10635   PetscCall(PetscFree(matcolor->rows));
10636   PetscCall(PetscFree(matcolor->den2sp));
10637   PetscCall(PetscFree(matcolor->colorforcol));
10638   PetscCall(PetscFree(matcolor->columns));
10639   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10640   PetscCall(PetscHeaderDestroy(c));
10641   PetscFunctionReturn(PETSC_SUCCESS);
10642 }
10643 
10644 /*@C
10645     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10646     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10647     `MatTransposeColoring` to sparse B.
10648 
10649     Collective
10650 
10651     Input Parameters:
10652 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10653 -   B - sparse matrix
10654 
10655     Output Parameter:
10656 .   Btdense - dense matrix B^T
10657 
10658     Level: developer
10659 
10660     Note:
10661     These are used internally for some implementations of `MatRARt()`
10662 
10663 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10664 @*/
10665 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10666 {
10667   PetscFunctionBegin;
10668   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10669   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10670   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10671 
10672   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10673   PetscFunctionReturn(PETSC_SUCCESS);
10674 }
10675 
10676 /*@C
10677     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10678     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10679     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10680     `Csp` from `Cden`.
10681 
10682     Collective
10683 
10684     Input Parameters:
10685 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10686 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10687 
10688     Output Parameter:
10689 .   Csp - sparse matrix
10690 
10691     Level: developer
10692 
10693     Note:
10694     These are used internally for some implementations of `MatRARt()`
10695 
10696 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10697 @*/
10698 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10699 {
10700   PetscFunctionBegin;
10701   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10702   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10703   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10704 
10705   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10706   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10707   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10708   PetscFunctionReturn(PETSC_SUCCESS);
10709 }
10710 
10711 /*@C
10712    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10713 
10714    Collective
10715 
10716    Input Parameters:
10717 +  mat - the matrix product C
10718 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10719 
10720     Output Parameter:
10721 .   color - the new coloring context
10722 
10723     Level: intermediate
10724 
10725 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10726           `MatTransColoringApplyDenToSp()`
10727 @*/
10728 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10729 {
10730   MatTransposeColoring c;
10731   MPI_Comm             comm;
10732 
10733   PetscFunctionBegin;
10734   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10735   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10736   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10737 
10738   c->ctype = iscoloring->ctype;
10739   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10740 
10741   *color = c;
10742   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10743   PetscFunctionReturn(PETSC_SUCCESS);
10744 }
10745 
10746 /*@
10747       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10748         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10749         same, otherwise it will be larger
10750 
10751      Not Collective
10752 
10753   Input Parameter:
10754 .    A  - the matrix
10755 
10756   Output Parameter:
10757 .    state - the current state
10758 
10759   Level: intermediate
10760 
10761   Notes:
10762     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10763          different matrices
10764 
10765     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10766 
10767     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10768 
10769 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10770 @*/
10771 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10772 {
10773   PetscFunctionBegin;
10774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10775   *state = mat->nonzerostate;
10776   PetscFunctionReturn(PETSC_SUCCESS);
10777 }
10778 
10779 /*@
10780       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10781                  matrices from each processor
10782 
10783     Collective
10784 
10785    Input Parameters:
10786 +    comm - the communicators the parallel matrix will live on
10787 .    seqmat - the input sequential matrices
10788 .    n - number of local columns (or `PETSC_DECIDE`)
10789 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10790 
10791    Output Parameter:
10792 .    mpimat - the parallel matrix generated
10793 
10794     Level: developer
10795 
10796    Note:
10797     The number of columns of the matrix in EACH processor MUST be the same.
10798 
10799 .seealso: [](chapter_matrices), `Mat`
10800 @*/
10801 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10802 {
10803   PetscMPIInt size;
10804 
10805   PetscFunctionBegin;
10806   PetscCallMPI(MPI_Comm_size(comm, &size));
10807   if (size == 1) {
10808     if (reuse == MAT_INITIAL_MATRIX) {
10809       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10810     } else {
10811       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10812     }
10813     PetscFunctionReturn(PETSC_SUCCESS);
10814   }
10815 
10816   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");
10817 
10818   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10819   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10820   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10821   PetscFunctionReturn(PETSC_SUCCESS);
10822 }
10823 
10824 /*@
10825      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10826 
10827     Collective
10828 
10829    Input Parameters:
10830 +    A   - the matrix to create subdomains from
10831 -    N   - requested number of subdomains
10832 
10833    Output Parameters:
10834 +    n   - number of subdomains resulting on this rank
10835 -    iss - `IS` list with indices of subdomains on this rank
10836 
10837     Level: advanced
10838 
10839     Note:
10840     The number of subdomains must be smaller than the communicator size
10841 
10842 .seealso: [](chapter_matrices), `Mat`, `IS`
10843 @*/
10844 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10845 {
10846   MPI_Comm    comm, subcomm;
10847   PetscMPIInt size, rank, color;
10848   PetscInt    rstart, rend, k;
10849 
10850   PetscFunctionBegin;
10851   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10852   PetscCallMPI(MPI_Comm_size(comm, &size));
10853   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10854   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);
10855   *n    = 1;
10856   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10857   color = rank / k;
10858   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10859   PetscCall(PetscMalloc1(1, iss));
10860   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10861   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10862   PetscCallMPI(MPI_Comm_free(&subcomm));
10863   PetscFunctionReturn(PETSC_SUCCESS);
10864 }
10865 
10866 /*@
10867    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10868 
10869    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10870    If they are not the same, uses `MatMatMatMult()`.
10871 
10872    Once the coarse grid problem is constructed, correct for interpolation operators
10873    that are not of full rank, which can legitimately happen in the case of non-nested
10874    geometric multigrid.
10875 
10876    Input Parameters:
10877 +  restrct - restriction operator
10878 .  dA - fine grid matrix
10879 .  interpolate - interpolation operator
10880 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10881 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10882 
10883    Output Parameter:
10884 .  A - the Galerkin coarse matrix
10885 
10886    Options Database Key:
10887 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10888 
10889    Level: developer
10890 
10891 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10892 @*/
10893 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10894 {
10895   IS  zerorows;
10896   Vec diag;
10897 
10898   PetscFunctionBegin;
10899   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10900   /* Construct the coarse grid matrix */
10901   if (interpolate == restrct) {
10902     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10903   } else {
10904     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10905   }
10906 
10907   /* If the interpolation matrix is not of full rank, A will have zero rows.
10908      This can legitimately happen in the case of non-nested geometric multigrid.
10909      In that event, we set the rows of the matrix to the rows of the identity,
10910      ignoring the equations (as the RHS will also be zero). */
10911 
10912   PetscCall(MatFindZeroRows(*A, &zerorows));
10913 
10914   if (zerorows != NULL) { /* if there are any zero rows */
10915     PetscCall(MatCreateVecs(*A, &diag, NULL));
10916     PetscCall(MatGetDiagonal(*A, diag));
10917     PetscCall(VecISSet(diag, zerorows, 1.0));
10918     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10919     PetscCall(VecDestroy(&diag));
10920     PetscCall(ISDestroy(&zerorows));
10921   }
10922   PetscFunctionReturn(PETSC_SUCCESS);
10923 }
10924 
10925 /*@C
10926     MatSetOperation - Allows user to set a matrix operation for any matrix type
10927 
10928    Logically Collective
10929 
10930     Input Parameters:
10931 +   mat - the matrix
10932 .   op - the name of the operation
10933 -   f - the function that provides the operation
10934 
10935    Level: developer
10936 
10937     Usage:
10938 .vb
10939   extern PetscErrorCode usermult(Mat, Vec, Vec);
10940 
10941   PetscCall(MatCreateXXX(comm, ..., &A));
10942   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10943 .ve
10944 
10945     Notes:
10946     See the file `include/petscmat.h` for a complete list of matrix
10947     operations, which all have the form MATOP_<OPERATION>, where
10948     <OPERATION> is the name (in all capital letters) of the
10949     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10950 
10951     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10952     sequence as the usual matrix interface routines, since they
10953     are intended to be accessed via the usual matrix interface
10954     routines, e.g.,
10955 .vb
10956   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10957 .ve
10958 
10959     In particular each function MUST return `PETSC_SUCCESS` on success and
10960     nonzero on failure.
10961 
10962     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10963 
10964 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10965 @*/
10966 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10967 {
10968   PetscFunctionBegin;
10969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10970   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10971   (((void (**)(void))mat->ops)[op]) = f;
10972   PetscFunctionReturn(PETSC_SUCCESS);
10973 }
10974 
10975 /*@C
10976     MatGetOperation - Gets a matrix operation for any matrix type.
10977 
10978     Not Collective
10979 
10980     Input Parameters:
10981 +   mat - the matrix
10982 -   op - the name of the operation
10983 
10984     Output Parameter:
10985 .   f - the function that provides the operation
10986 
10987     Level: developer
10988 
10989     Usage:
10990 .vb
10991       PetscErrorCode (*usermult)(Mat, Vec, Vec);
10992       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
10993 .ve
10994 
10995     Notes:
10996     See the file include/petscmat.h for a complete list of matrix
10997     operations, which all have the form MATOP_<OPERATION>, where
10998     <OPERATION> is the name (in all capital letters) of the
10999     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11000 
11001     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11002 
11003 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11004 @*/
11005 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11006 {
11007   PetscFunctionBegin;
11008   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11009   *f = (((void (**)(void))mat->ops)[op]);
11010   PetscFunctionReturn(PETSC_SUCCESS);
11011 }
11012 
11013 /*@
11014     MatHasOperation - Determines whether the given matrix supports the particular operation.
11015 
11016    Not Collective
11017 
11018    Input Parameters:
11019 +  mat - the matrix
11020 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11021 
11022    Output Parameter:
11023 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11024 
11025    Level: advanced
11026 
11027    Note:
11028    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11029 
11030 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11031 @*/
11032 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11033 {
11034   PetscFunctionBegin;
11035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11036   PetscValidBoolPointer(has, 3);
11037   if (mat->ops->hasoperation) {
11038     PetscUseTypeMethod(mat, hasoperation, op, has);
11039   } else {
11040     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11041     else {
11042       *has = PETSC_FALSE;
11043       if (op == MATOP_CREATE_SUBMATRIX) {
11044         PetscMPIInt size;
11045 
11046         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11047         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11048       }
11049     }
11050   }
11051   PetscFunctionReturn(PETSC_SUCCESS);
11052 }
11053 
11054 /*@
11055     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11056 
11057    Collective
11058 
11059    Input Parameter:
11060 .  mat - the matrix
11061 
11062    Output Parameter:
11063 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11064 
11065    Level: beginner
11066 
11067 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11068 @*/
11069 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11070 {
11071   PetscFunctionBegin;
11072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11073   PetscValidType(mat, 1);
11074   PetscValidBoolPointer(cong, 2);
11075   if (!mat->rmap || !mat->cmap) {
11076     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11077     PetscFunctionReturn(PETSC_SUCCESS);
11078   }
11079   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11080     PetscCall(PetscLayoutSetUp(mat->rmap));
11081     PetscCall(PetscLayoutSetUp(mat->cmap));
11082     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11083     if (*cong) mat->congruentlayouts = 1;
11084     else mat->congruentlayouts = 0;
11085   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11086   PetscFunctionReturn(PETSC_SUCCESS);
11087 }
11088 
11089 PetscErrorCode MatSetInf(Mat A)
11090 {
11091   PetscFunctionBegin;
11092   PetscUseTypeMethod(A, setinf);
11093   PetscFunctionReturn(PETSC_SUCCESS);
11094 }
11095 
11096 /*@C
11097    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
11098    and possibly removes small values from the graph structure.
11099 
11100    Collective
11101 
11102    Input Parameters:
11103 +  A - the matrix
11104 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11105 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11106 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11107 
11108    Output Parameter:
11109 .  graph - the resulting graph
11110 
11111    Level: advanced
11112 
11113 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11114 @*/
11115 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11116 {
11117   PetscFunctionBegin;
11118   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11119   PetscValidType(A, 1);
11120   PetscValidLogicalCollectiveBool(A, scale, 3);
11121   PetscValidPointer(graph, 5);
11122   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11123   PetscFunctionReturn(PETSC_SUCCESS);
11124 }
11125 
11126 /*@
11127   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11128   meaning the same memory is used for the matrix, and no new memory is allocated.
11129 
11130   Collective
11131 
11132   Input Parameter:
11133 . A - the matrix
11134 
11135   Level: intermediate
11136 
11137   Developer Note:
11138   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11139   of the arrays in the data structure are unneeded.
11140 
11141 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11142 @*/
11143 PetscErrorCode MatEliminateZeros(Mat A)
11144 {
11145   PetscFunctionBegin;
11146   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11147   PetscUseTypeMethod(A, eliminatezeros);
11148   PetscFunctionReturn(PETSC_SUCCESS);
11149 }
11150