xref: /petsc/src/mat/interface/matrix.c (revision 79560b15e0158833da0988de9f5c4f3b41291c0c)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](ch_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](ch_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameter:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameter:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
899   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
900   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
901   PetscFunctionReturn(PETSC_SUCCESS);
902 }
903 
904 /*@
905    MatSetUp - Sets up the internal matrix data structures for later use.
906 
907    Collective
908 
909    Input Parameter:
910 .  A - the matrix
911 
912    Level: intermediate
913 
914    Notes:
915    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
916    setting values in the matrix.
917 
918    If a suitable preallocation routine is used, this function does not need to be called.
919 
920    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
921 
922 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
923 @*/
924 PetscErrorCode MatSetUp(Mat A)
925 {
926   PetscFunctionBegin;
927   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
928   if (!((PetscObject)A)->type_name) {
929     PetscMPIInt size;
930 
931     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
932     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
933   }
934   if (!A->preallocated) PetscTryTypeMethod(A, setup);
935   PetscCall(PetscLayoutSetUp(A->rmap));
936   PetscCall(PetscLayoutSetUp(A->cmap));
937   A->preallocated = PETSC_TRUE;
938   PetscFunctionReturn(PETSC_SUCCESS);
939 }
940 
941 #if defined(PETSC_HAVE_SAWS)
942   #include <petscviewersaws.h>
943 #endif
944 
945 /*
946    If threadsafety is on extraneous matrices may be printed
947 
948    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
949 */
950 #if !defined(PETSC_HAVE_THREADSAFETY)
951 static PetscInt insidematview = 0;
952 #endif
953 
954 /*@C
955    MatViewFromOptions - View properties of the matrix based on options set in the options database
956 
957    Collective
958 
959    Input Parameters:
960 +  A - the matrix
961 .  obj - optional additional object that provides the options prefix to use
962 -  name - command line option
963 
964   Options Database Key:
965 .  -mat_view [viewertype]:... - the viewer and its options
966 
967    Level: intermediate
968 
969   Notes:
970 .vb
971     If no value is provided ascii:stdout is used
972        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
973                                                   for example ascii::ascii_info prints just the information about the object not all details
974                                                   unless :append is given filename opens in write mode, overwriting what was already there
975        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
976        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
977        socket[:port]                             defaults to the standard output port
978        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
979 .ve
980 
981 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
982 @*/
983 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
984 {
985   PetscFunctionBegin;
986   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
987 #if !defined(PETSC_HAVE_THREADSAFETY)
988   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
989 #endif
990   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
991   PetscFunctionReturn(PETSC_SUCCESS);
992 }
993 
994 /*@C
995    MatView - display information about a matrix in a variety ways
996 
997    Collective
998 
999    Input Parameters:
1000 +  mat - the matrix
1001 -  viewer - visualization context
1002 
1003    Options Database Keys:
1004 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1005 .  -mat_view ::ascii_info_detail - Prints more detailed info
1006 .  -mat_view - Prints matrix in ASCII format
1007 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1008 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1009 .  -display <name> - Sets display name (default is host)
1010 .  -draw_pause <sec> - Sets number of seconds to pause after display
1011 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1012 .  -viewer_socket_machine <machine> -
1013 .  -viewer_socket_port <port> -
1014 .  -mat_view binary - save matrix to file in binary format
1015 -  -viewer_binary_filename <name> -
1016 
1017    Level: beginner
1018 
1019   Notes:
1020   The available visualization contexts include
1021 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1022 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1023 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1024 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1025 
1026    The user can open alternative visualization contexts with
1027 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1028 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1029          specified file; corresponding input uses `MatLoad()`
1030 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1031          an X window display
1032 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1033          Currently only the `MATSEQDENSE` and `MATAIJ`
1034          matrix types support the Socket viewer.
1035 
1036    The user can call `PetscViewerPushFormat()` to specify the output
1037    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1038    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1039 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1040 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1041 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1042 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1043          format common among all matrix types
1044 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1045          format (which is in many cases the same as the default)
1046 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1047          size and structure (not the matrix entries)
1048 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1049          the matrix structure
1050 
1051     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1052     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1053 
1054     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1055 
1056     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1057       viewer is used.
1058 
1059       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1060       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1061 
1062       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1063       and then use the following mouse functions.
1064 .vb
1065   left mouse: zoom in
1066   middle mouse: zoom out
1067   right mouse: continue with the simulation
1068 .ve
1069 
1070 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1071           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1072 @*/
1073 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1074 {
1075   PetscInt          rows, cols, rbs, cbs;
1076   PetscBool         isascii, isstring, issaws;
1077   PetscViewerFormat format;
1078   PetscMPIInt       size;
1079 
1080   PetscFunctionBegin;
1081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1082   PetscValidType(mat, 1);
1083   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1084   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1085   PetscCheckSameComm(mat, 1, viewer, 2);
1086 
1087   PetscCall(PetscViewerGetFormat(viewer, &format));
1088   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1089   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1090 
1091 #if !defined(PETSC_HAVE_THREADSAFETY)
1092   insidematview++;
1093 #endif
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1097   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");
1098 
1099   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1100   if (isascii) {
1101     if (!mat->preallocated) {
1102       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1103 #if !defined(PETSC_HAVE_THREADSAFETY)
1104       insidematview--;
1105 #endif
1106       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1107       PetscFunctionReturn(PETSC_SUCCESS);
1108     }
1109     if (!mat->assembled) {
1110       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1111 #if !defined(PETSC_HAVE_THREADSAFETY)
1112       insidematview--;
1113 #endif
1114       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1115       PetscFunctionReturn(PETSC_SUCCESS);
1116     }
1117     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1118     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1119       MatNullSpace nullsp, transnullsp;
1120 
1121       PetscCall(PetscViewerASCIIPushTab(viewer));
1122       PetscCall(MatGetSize(mat, &rows, &cols));
1123       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1124       if (rbs != 1 || cbs != 1) {
1125         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1126         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1127       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1128       if (mat->factortype) {
1129         MatSolverType solver;
1130         PetscCall(MatFactorGetSolverType(mat, &solver));
1131         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1132       }
1133       if (mat->ops->getinfo) {
1134         MatInfo info;
1135         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1136         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1137         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1138       }
1139       PetscCall(MatGetNullSpace(mat, &nullsp));
1140       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1141       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1142       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1143       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1144       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1145       PetscCall(PetscViewerASCIIPushTab(viewer));
1146       PetscCall(MatProductView(mat, viewer));
1147       PetscCall(PetscViewerASCIIPopTab(viewer));
1148     }
1149   } else if (issaws) {
1150 #if defined(PETSC_HAVE_SAWS)
1151     PetscMPIInt rank;
1152 
1153     PetscCall(PetscObjectName((PetscObject)mat));
1154     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1155     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1156 #endif
1157   } else if (isstring) {
1158     const char *type;
1159     PetscCall(MatGetType(mat, &type));
1160     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1161     PetscTryTypeMethod(mat, view, viewer);
1162   }
1163   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1164     PetscCall(PetscViewerASCIIPushTab(viewer));
1165     PetscUseTypeMethod(mat, viewnative, viewer);
1166     PetscCall(PetscViewerASCIIPopTab(viewer));
1167   } else if (mat->ops->view) {
1168     PetscCall(PetscViewerASCIIPushTab(viewer));
1169     PetscUseTypeMethod(mat, view, viewer);
1170     PetscCall(PetscViewerASCIIPopTab(viewer));
1171   }
1172   if (isascii) {
1173     PetscCall(PetscViewerGetFormat(viewer, &format));
1174     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1175   }
1176   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1177 #if !defined(PETSC_HAVE_THREADSAFETY)
1178   insidematview--;
1179 #endif
1180   PetscFunctionReturn(PETSC_SUCCESS);
1181 }
1182 
1183 #if defined(PETSC_USE_DEBUG)
1184   #include <../src/sys/totalview/tv_data_display.h>
1185 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1186 {
1187   TV_add_row("Local rows", "int", &mat->rmap->n);
1188   TV_add_row("Local columns", "int", &mat->cmap->n);
1189   TV_add_row("Global rows", "int", &mat->rmap->N);
1190   TV_add_row("Global columns", "int", &mat->cmap->N);
1191   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1192   return TV_format_OK;
1193 }
1194 #endif
1195 
1196 /*@C
1197    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1198    with `MatView()`.  The matrix format is determined from the options database.
1199    Generates a parallel MPI matrix if the communicator has more than one
1200    processor.  The default matrix type is `MATAIJ`.
1201 
1202    Collective
1203 
1204    Input Parameters:
1205 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1206             or some related function before a call to `MatLoad()`
1207 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1208 
1209    Options Database Keys:
1210    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1211    block size
1212 .    -matload_block_size <bs> - set block size
1213 
1214    Level: beginner
1215 
1216    Notes:
1217    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1218    `Mat` before calling this routine if you wish to set it from the options database.
1219 
1220    `MatLoad()` automatically loads into the options database any options
1221    given in the file filename.info where filename is the name of the file
1222    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1223    file will be ignored if you use the -viewer_binary_skip_info option.
1224 
1225    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1226    sets the default matrix type AIJ and sets the local and global sizes.
1227    If type and/or size is already set, then the same are used.
1228 
1229    In parallel, each processor can load a subset of rows (or the
1230    entire matrix).  This routine is especially useful when a large
1231    matrix is stored on disk and only part of it is desired on each
1232    processor.  For example, a parallel solver may access only some of
1233    the rows from each processor.  The algorithm used here reads
1234    relatively small blocks of data rather than reading the entire
1235    matrix and then subsetting it.
1236 
1237    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1238    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1239    or the sequence like
1240 .vb
1241     `PetscViewer` v;
1242     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1243     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1244     `PetscViewerSetFromOptions`(v);
1245     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1246     `PetscViewerFileSetName`(v,"datafile");
1247 .ve
1248    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1249 $ -viewer_type {binary, hdf5}
1250 
1251    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1252    and src/mat/tutorials/ex10.c with the second approach.
1253 
1254    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1255    is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1256    Multiple objects, both matrices and vectors, can be stored within the same file.
1257    Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1258 
1259    Most users should not need to know the details of the binary storage
1260    format, since `MatLoad()` and `MatView()` completely hide these details.
1261    But for anyone who is interested, the standard binary matrix storage
1262    format is
1263 
1264 .vb
1265     PetscInt    MAT_FILE_CLASSID
1266     PetscInt    number of rows
1267     PetscInt    number of columns
1268     PetscInt    total number of nonzeros
1269     PetscInt    *number nonzeros in each row
1270     PetscInt    *column indices of all nonzeros (starting index is zero)
1271     PetscScalar *values of all nonzeros
1272 .ve
1273    If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1274    stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1275    case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1276 
1277    PETSc automatically does the byte swapping for
1278    machines that store the bytes reversed. Thus if you write your own binary
1279    read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1280    and `PetscBinaryWrite()` to see how this may be done.
1281 
1282    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1283    Each processor's chunk is loaded independently by its owning MPI process.
1284    Multiple objects, both matrices and vectors, can be stored within the same file.
1285    They are looked up by their PetscObject name.
1286 
1287    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1288    by default the same structure and naming of the AIJ arrays and column count
1289    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1290 $    save example.mat A b -v7.3
1291    can be directly read by this routine (see Reference 1 for details).
1292 
1293    Depending on your MATLAB version, this format might be a default,
1294    otherwise you can set it as default in Preferences.
1295 
1296    Unless -nocompression flag is used to save the file in MATLAB,
1297    PETSc must be configured with ZLIB package.
1298 
1299    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1300 
1301    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1302 
1303    Corresponding `MatView()` is not yet implemented.
1304 
1305    The loaded matrix is actually a transpose of the original one in MATLAB,
1306    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1307    With this format, matrix is automatically transposed by PETSc,
1308    unless the matrix is marked as SPD or symmetric
1309    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1310 
1311    References:
1312 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1313 
1314 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1315  @*/
1316 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1317 {
1318   PetscBool flg;
1319 
1320   PetscFunctionBegin;
1321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1322   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1323 
1324   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1325 
1326   flg = PETSC_FALSE;
1327   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1328   if (flg) {
1329     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1330     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1331   }
1332   flg = PETSC_FALSE;
1333   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1334   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1335 
1336   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1337   PetscUseTypeMethod(mat, load, viewer);
1338   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1339   PetscFunctionReturn(PETSC_SUCCESS);
1340 }
1341 
1342 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1343 {
1344   Mat_Redundant *redund = *redundant;
1345 
1346   PetscFunctionBegin;
1347   if (redund) {
1348     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1349       PetscCall(ISDestroy(&redund->isrow));
1350       PetscCall(ISDestroy(&redund->iscol));
1351       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1352     } else {
1353       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1354       PetscCall(PetscFree(redund->sbuf_j));
1355       PetscCall(PetscFree(redund->sbuf_a));
1356       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1357         PetscCall(PetscFree(redund->rbuf_j[i]));
1358         PetscCall(PetscFree(redund->rbuf_a[i]));
1359       }
1360       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1361     }
1362 
1363     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1364     PetscCall(PetscFree(redund));
1365   }
1366   PetscFunctionReturn(PETSC_SUCCESS);
1367 }
1368 
1369 /*@C
1370    MatDestroy - Frees space taken by a matrix.
1371 
1372    Collective
1373 
1374    Input Parameter:
1375 .  A - the matrix
1376 
1377    Level: beginner
1378 
1379    Developer Note:
1380    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1381    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1382    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1383    if changes are needed here.
1384 
1385 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1386 @*/
1387 PetscErrorCode MatDestroy(Mat *A)
1388 {
1389   PetscFunctionBegin;
1390   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1391   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1392   if (--((PetscObject)(*A))->refct > 0) {
1393     *A = NULL;
1394     PetscFunctionReturn(PETSC_SUCCESS);
1395   }
1396 
1397   /* if memory was published with SAWs then destroy it */
1398   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1399   PetscTryTypeMethod((*A), destroy);
1400 
1401   PetscCall(PetscFree((*A)->factorprefix));
1402   PetscCall(PetscFree((*A)->defaultvectype));
1403   PetscCall(PetscFree((*A)->defaultrandtype));
1404   PetscCall(PetscFree((*A)->bsizes));
1405   PetscCall(PetscFree((*A)->solvertype));
1406   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1407   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1408   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1409   PetscCall(MatProductClear(*A));
1410   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1411   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1412   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1413   PetscCall(MatDestroy(&(*A)->schur));
1414   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1415   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1416   PetscCall(PetscHeaderDestroy(A));
1417   PetscFunctionReturn(PETSC_SUCCESS);
1418 }
1419 
1420 /*@C
1421    MatSetValues - Inserts or adds a block of values into a matrix.
1422    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1423    MUST be called after all calls to `MatSetValues()` have been completed.
1424 
1425    Not Collective
1426 
1427    Input Parameters:
1428 +  mat - the matrix
1429 .  v - a logically two-dimensional array of values
1430 .  m - the number of rows
1431 .  idxm - the global indices of the rows
1432 .  n - the number of columns
1433 .  idxn - the global indices of the columns
1434 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1435 
1436    Level: beginner
1437 
1438    Notes:
1439    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1440 
1441    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1442    options cannot be mixed without intervening calls to the assembly
1443    routines.
1444 
1445    `MatSetValues()` uses 0-based row and column numbers in Fortran
1446    as well as in C.
1447 
1448    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1449    simply ignored. This allows easily inserting element stiffness matrices
1450    with homogeneous Dirchlet boundary conditions that you don't want represented
1451    in the matrix.
1452 
1453    Efficiency Alert:
1454    The routine `MatSetValuesBlocked()` may offer much better efficiency
1455    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1456 
1457    Developer Note:
1458    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1459    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1460 
1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1462           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1463 @*/
1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1465 {
1466   PetscFunctionBeginHot;
1467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1468   PetscValidType(mat, 1);
1469   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1470   PetscValidIntPointer(idxm, 3);
1471   PetscValidIntPointer(idxn, 5);
1472   MatCheckPreallocated(mat, 1);
1473 
1474   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1475   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1476 
1477   if (PetscDefined(USE_DEBUG)) {
1478     PetscInt i, j;
1479 
1480     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1481     for (i = 0; i < m; i++) {
1482       for (j = 0; j < n; j++) {
1483         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1484 #if defined(PETSC_USE_COMPLEX)
1485           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]);
1486 #else
1487           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]);
1488 #endif
1489       }
1490     }
1491     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);
1492     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);
1493   }
1494 
1495   if (mat->assembled) {
1496     mat->was_assembled = PETSC_TRUE;
1497     mat->assembled     = PETSC_FALSE;
1498   }
1499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1500   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1501   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1502   PetscFunctionReturn(PETSC_SUCCESS);
1503 }
1504 
1505 /*@C
1506    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1507    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1508    MUST be called after all calls to `MatSetValues()` have been completed.
1509 
1510    Not Collective
1511 
1512    Input Parameters:
1513 +  mat - the matrix
1514 .  v - a logically two-dimensional array of values
1515 .  ism - the rows to provide
1516 .  isn - the columns to provide
1517 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519    Level: beginner
1520 
1521    Notes:
1522    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525    options cannot be mixed without intervening calls to the assembly
1526    routines.
1527 
1528    `MatSetValues()` uses 0-based row and column numbers in Fortran
1529    as well as in C.
1530 
1531    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1532    simply ignored. This allows easily inserting element stiffness matrices
1533    with homogeneous Dirchlet boundary conditions that you don't want represented
1534    in the matrix.
1535 
1536    Efficiency Alert:
1537    The routine `MatSetValuesBlocked()` may offer much better efficiency
1538    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540     This is currently not optimized for any particular `ISType`
1541 
1542    Developer Notes:
1543     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1544                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1545 
1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1547           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1548 @*/
1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1550 {
1551   PetscInt        m, n;
1552   const PetscInt *rows, *cols;
1553 
1554   PetscFunctionBeginHot;
1555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1556   PetscCall(ISGetIndices(ism, &rows));
1557   PetscCall(ISGetIndices(isn, &cols));
1558   PetscCall(ISGetLocalSize(ism, &m));
1559   PetscCall(ISGetLocalSize(isn, &n));
1560   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1561   PetscCall(ISRestoreIndices(ism, &rows));
1562   PetscCall(ISRestoreIndices(isn, &cols));
1563   PetscFunctionReturn(PETSC_SUCCESS);
1564 }
1565 
1566 /*@
1567    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1568         values into a matrix
1569 
1570    Not Collective
1571 
1572    Input Parameters:
1573 +  mat - the matrix
1574 .  row - the (block) row to set
1575 -  v - a logically two-dimensional array of values
1576 
1577    Level: intermediate
1578 
1579    Notes:
1580    The values, `v`, are column-oriented (for the block version) and sorted
1581 
1582    All the nonzeros in the row must be provided
1583 
1584    The matrix must have previously had its column indices set, likely by having been assembled.
1585 
1586    The row must belong to this process
1587 
1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1589           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1590 @*/
1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1592 {
1593   PetscInt globalrow;
1594 
1595   PetscFunctionBegin;
1596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1597   PetscValidType(mat, 1);
1598   PetscValidScalarPointer(v, 3);
1599   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1600   PetscCall(MatSetValuesRow(mat, globalrow, v));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /*@
1605    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1606         values into a matrix
1607 
1608    Not Collective
1609 
1610    Input Parameters:
1611 +  mat - the matrix
1612 .  row - the (block) row to set
1613 -  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
1614 
1615    Level: advanced
1616 
1617    Notes:
1618    The values, `v`, are column-oriented for the block version.
1619 
1620    All the nonzeros in the row must be provided
1621 
1622    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1623 
1624    The row must belong to this process
1625 
1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1627           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1628 @*/
1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1630 {
1631   PetscFunctionBeginHot;
1632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1633   PetscValidType(mat, 1);
1634   MatCheckPreallocated(mat, 1);
1635   PetscValidScalarPointer(v, 3);
1636   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1637   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1638   mat->insertmode = INSERT_VALUES;
1639 
1640   if (mat->assembled) {
1641     mat->was_assembled = PETSC_TRUE;
1642     mat->assembled     = PETSC_FALSE;
1643   }
1644   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1645   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1646   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 /*@
1651    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1652      Using structured grid indexing
1653 
1654    Not Collective
1655 
1656    Input Parameters:
1657 +  mat - the matrix
1658 .  m - number of rows being entered
1659 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1660 .  n - number of columns being entered
1661 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1662 .  v - a logically two-dimensional array of values
1663 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1664 
1665    Level: beginner
1666 
1667    Notes:
1668    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1669 
1670    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1671    options cannot be mixed without intervening calls to the assembly
1672    routines.
1673 
1674    The grid coordinates are across the entire grid, not just the local portion
1675 
1676    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1677    as well as in C.
1678 
1679    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1680 
1681    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1682    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1683 
1684    The columns and rows in the stencil passed in MUST be contained within the
1685    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1686    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1687    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1688    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1689 
1690    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1691    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1692    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1693    `DM_BOUNDARY_PERIODIC` boundary type.
1694 
1695    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
1696    a single value per point) you can skip filling those indices.
1697 
1698    Inspired by the structured grid interface to the HYPRE package
1699    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1700 
1701    Efficiency Alert:
1702    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1703    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1704 
1705    Fortran Note:
1706    `idxm` and `idxn` should be declared as
1707 $     MatStencil idxm(4,m),idxn(4,n)
1708    and the values inserted using
1709 .vb
1710     idxm(MatStencil_i,1) = i
1711     idxm(MatStencil_j,1) = j
1712     idxm(MatStencil_k,1) = k
1713     idxm(MatStencil_c,1) = c
1714     etc
1715 .ve
1716 
1717 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1718           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1719 @*/
1720 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1721 {
1722   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1723   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1724   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1725 
1726   PetscFunctionBegin;
1727   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1729   PetscValidType(mat, 1);
1730   PetscValidPointer(idxm, 3);
1731   PetscValidPointer(idxn, 5);
1732 
1733   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1734     jdxm = buf;
1735     jdxn = buf + m;
1736   } else {
1737     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1738     jdxm = bufm;
1739     jdxn = bufn;
1740   }
1741   for (i = 0; i < m; i++) {
1742     for (j = 0; j < 3 - sdim; j++) dxm++;
1743     tmp = *dxm++ - starts[0];
1744     for (j = 0; j < dim - 1; j++) {
1745       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1746       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1747     }
1748     if (mat->stencil.noc) dxm++;
1749     jdxm[i] = tmp;
1750   }
1751   for (i = 0; i < n; i++) {
1752     for (j = 0; j < 3 - sdim; j++) dxn++;
1753     tmp = *dxn++ - starts[0];
1754     for (j = 0; j < dim - 1; j++) {
1755       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1756       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1757     }
1758     if (mat->stencil.noc) dxn++;
1759     jdxn[i] = tmp;
1760   }
1761   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1762   PetscCall(PetscFree2(bufm, bufn));
1763   PetscFunctionReturn(PETSC_SUCCESS);
1764 }
1765 
1766 /*@
1767    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1768      Using structured grid indexing
1769 
1770    Not Collective
1771 
1772    Input Parameters:
1773 +  mat - the matrix
1774 .  m - number of rows being entered
1775 .  idxm - grid coordinates for matrix rows being entered
1776 .  n - number of columns being entered
1777 .  idxn - grid coordinates for matrix columns being entered
1778 .  v - a logically two-dimensional array of values
1779 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1780 
1781    Level: beginner
1782 
1783    Notes:
1784    By default the values, `v`, are row-oriented and unsorted.
1785    See `MatSetOption()` for other options.
1786 
1787    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1788    options cannot be mixed without intervening calls to the assembly
1789    routines.
1790 
1791    The grid coordinates are across the entire grid, not just the local portion
1792 
1793    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1794    as well as in C.
1795 
1796    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1797 
1798    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1799    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1800 
1801    The columns and rows in the stencil passed in MUST be contained within the
1802    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1803    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1804    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1805    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1806 
1807    Negative indices may be passed in idxm and idxn, these rows and columns are
1808    simply ignored. This allows easily inserting element stiffness matrices
1809    with homogeneous Dirchlet boundary conditions that you don't want represented
1810    in the matrix.
1811 
1812    Inspired by the structured grid interface to the HYPRE package
1813    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1814 
1815    Fortran Note:
1816    `idxm` and `idxn` should be declared as
1817 $     MatStencil idxm(4,m),idxn(4,n)
1818    and the values inserted using
1819 .vb
1820     idxm(MatStencil_i,1) = i
1821     idxm(MatStencil_j,1) = j
1822     idxm(MatStencil_k,1) = k
1823    etc
1824 .ve
1825 
1826 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1827           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1828           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1829 @*/
1830 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1831 {
1832   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1833   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1834   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1835 
1836   PetscFunctionBegin;
1837   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1839   PetscValidType(mat, 1);
1840   PetscValidPointer(idxm, 3);
1841   PetscValidPointer(idxn, 5);
1842   PetscValidScalarPointer(v, 6);
1843 
1844   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1845     jdxm = buf;
1846     jdxn = buf + m;
1847   } else {
1848     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1849     jdxm = bufm;
1850     jdxn = bufn;
1851   }
1852   for (i = 0; i < m; i++) {
1853     for (j = 0; j < 3 - sdim; j++) dxm++;
1854     tmp = *dxm++ - starts[0];
1855     for (j = 0; j < sdim - 1; j++) {
1856       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1857       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1858     }
1859     dxm++;
1860     jdxm[i] = tmp;
1861   }
1862   for (i = 0; i < n; i++) {
1863     for (j = 0; j < 3 - sdim; j++) dxn++;
1864     tmp = *dxn++ - starts[0];
1865     for (j = 0; j < sdim - 1; j++) {
1866       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1867       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1868     }
1869     dxn++;
1870     jdxn[i] = tmp;
1871   }
1872   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1873   PetscCall(PetscFree2(bufm, bufn));
1874   PetscFunctionReturn(PETSC_SUCCESS);
1875 }
1876 
1877 /*@
1878    MatSetStencil - Sets the grid information for setting values into a matrix via
1879         `MatSetValuesStencil()`
1880 
1881    Not Collective
1882 
1883    Input Parameters:
1884 +  mat - the matrix
1885 .  dim - dimension of the grid 1, 2, or 3
1886 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1887 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1888 -  dof - number of degrees of freedom per node
1889 
1890    Level: beginner
1891 
1892    Notes:
1893    Inspired by the structured grid interface to the HYPRE package
1894    (www.llnl.gov/CASC/hyper)
1895 
1896    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1897    user.
1898 
1899 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1900           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1901 @*/
1902 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1903 {
1904   PetscFunctionBegin;
1905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1906   PetscValidIntPointer(dims, 3);
1907   PetscValidIntPointer(starts, 4);
1908 
1909   mat->stencil.dim = dim + (dof > 1);
1910   for (PetscInt i = 0; i < dim; i++) {
1911     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1912     mat->stencil.starts[i] = starts[dim - i - 1];
1913   }
1914   mat->stencil.dims[dim]   = dof;
1915   mat->stencil.starts[dim] = 0;
1916   mat->stencil.noc         = (PetscBool)(dof == 1);
1917   PetscFunctionReturn(PETSC_SUCCESS);
1918 }
1919 
1920 /*@C
1921    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1922 
1923    Not Collective
1924 
1925    Input Parameters:
1926 +  mat - the matrix
1927 .  v - a logically two-dimensional array of values
1928 .  m  - the number of block rows
1929 .  idxm - the global block indices
1930 .  n - the number of block columns
1931 .  idxn - the global block indices
1932 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1933 
1934    Level: intermediate
1935 
1936    Notes:
1937    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1938    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1939 
1940    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1941    NOT the total number of rows/columns; for example, if the block size is 2 and
1942    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1943    The values in idxm would be 1 2; that is the first index for each block divided by
1944    the block size.
1945 
1946    You must call `MatSetBlockSize()` when constructing this matrix (before
1947    preallocating it).
1948 
1949    By default the values, `v`, are row-oriented, so the layout of
1950    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1951 
1952    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1953    options cannot be mixed without intervening calls to the assembly
1954    routines.
1955 
1956    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1957    as well as in C.
1958 
1959    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1960    simply ignored. This allows easily inserting element stiffness matrices
1961    with homogeneous Dirchlet boundary conditions that you don't want represented
1962    in the matrix.
1963 
1964    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1965    internal searching must be done to determine where to place the
1966    data in the matrix storage space.  By instead inserting blocks of
1967    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1968    reduced.
1969 
1970    Example:
1971 .vb
1972    Suppose m=n=2 and block size(bs) = 2 The array is
1973 
1974    1  2  | 3  4
1975    5  6  | 7  8
1976    - - - | - - -
1977    9  10 | 11 12
1978    13 14 | 15 16
1979 
1980    v[] should be passed in like
1981    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1982 
1983   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1984    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1985 .ve
1986 
1987 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1988 @*/
1989 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1990 {
1991   PetscFunctionBeginHot;
1992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1993   PetscValidType(mat, 1);
1994   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1995   PetscValidIntPointer(idxm, 3);
1996   PetscValidIntPointer(idxn, 5);
1997   MatCheckPreallocated(mat, 1);
1998   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1999   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2000   if (PetscDefined(USE_DEBUG)) {
2001     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2002     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2003   }
2004   if (PetscDefined(USE_DEBUG)) {
2005     PetscInt rbs, cbs, M, N, i;
2006     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2007     PetscCall(MatGetSize(mat, &M, &N));
2008     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);
2009     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);
2010   }
2011   if (mat->assembled) {
2012     mat->was_assembled = PETSC_TRUE;
2013     mat->assembled     = PETSC_FALSE;
2014   }
2015   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2016   if (mat->ops->setvaluesblocked) {
2017     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2018   } else {
2019     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2020     PetscInt i, j, bs, cbs;
2021 
2022     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2023     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2024       iidxm = buf;
2025       iidxn = buf + m * bs;
2026     } else {
2027       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2028       iidxm = bufr;
2029       iidxn = bufc;
2030     }
2031     for (i = 0; i < m; i++) {
2032       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2033     }
2034     if (m != n || bs != cbs || idxm != idxn) {
2035       for (i = 0; i < n; i++) {
2036         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2037       }
2038     } else iidxn = iidxm;
2039     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2040     PetscCall(PetscFree2(bufr, bufc));
2041   }
2042   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2043   PetscFunctionReturn(PETSC_SUCCESS);
2044 }
2045 
2046 /*@C
2047    MatGetValues - Gets a block of local values from a matrix.
2048 
2049    Not Collective; can only return values that are owned by the give process
2050 
2051    Input Parameters:
2052 +  mat - the matrix
2053 .  v - a logically two-dimensional array for storing the values
2054 .  m  - the number of rows
2055 .  idxm - the  global indices of the rows
2056 .  n - the number of columns
2057 -  idxn - the global indices of the columns
2058 
2059    Level: advanced
2060 
2061    Notes:
2062      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2063      The values, `v`, are then returned in a row-oriented format,
2064      analogous to that used by default in `MatSetValues()`.
2065 
2066      `MatGetValues()` uses 0-based row and column numbers in
2067      Fortran as well as in C.
2068 
2069      `MatGetValues()` requires that the matrix has been assembled
2070      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2071      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2072      without intermediate matrix assembly.
2073 
2074      Negative row or column indices will be ignored and those locations in `v` will be
2075      left unchanged.
2076 
2077      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2078      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2079      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2080 
2081 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2082 @*/
2083 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2084 {
2085   PetscFunctionBegin;
2086   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2087   PetscValidType(mat, 1);
2088   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2089   PetscValidIntPointer(idxm, 3);
2090   PetscValidIntPointer(idxn, 5);
2091   PetscValidScalarPointer(v, 6);
2092   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2093   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2094   MatCheckPreallocated(mat, 1);
2095 
2096   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2097   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2098   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2099   PetscFunctionReturn(PETSC_SUCCESS);
2100 }
2101 
2102 /*@C
2103    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2104      defined previously by `MatSetLocalToGlobalMapping()`
2105 
2106    Not Collective
2107 
2108    Input Parameters:
2109 +  mat - the matrix
2110 .  nrow - number of rows
2111 .  irow - the row local indices
2112 .  ncol - number of columns
2113 -  icol - the column local indices
2114 
2115    Output Parameter:
2116 .  y -  a logically two-dimensional array of values
2117 
2118    Level: advanced
2119 
2120    Notes:
2121      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2122 
2123      This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2124      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2125      determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2126      with `MatSetLocalToGlobalMapping()`.
2127 
2128    Developer Note:
2129       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2130       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2131 
2132 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2133           `MatSetValuesLocal()`, `MatGetValues()`
2134 @*/
2135 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2136 {
2137   PetscFunctionBeginHot;
2138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2139   PetscValidType(mat, 1);
2140   MatCheckPreallocated(mat, 1);
2141   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2142   PetscValidIntPointer(irow, 3);
2143   PetscValidIntPointer(icol, 5);
2144   if (PetscDefined(USE_DEBUG)) {
2145     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2146     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2147   }
2148   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2149   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2150   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2151   else {
2152     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2153     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2154       irowm = buf;
2155       icolm = buf + nrow;
2156     } else {
2157       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2158       irowm = bufr;
2159       icolm = bufc;
2160     }
2161     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2162     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2163     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2164     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2165     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2166     PetscCall(PetscFree2(bufr, bufc));
2167   }
2168   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2169   PetscFunctionReturn(PETSC_SUCCESS);
2170 }
2171 
2172 /*@
2173   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2174   the same size. Currently, this can only be called once and creates the given matrix.
2175 
2176   Not Collective
2177 
2178   Input Parameters:
2179 + mat - the matrix
2180 . nb - the number of blocks
2181 . bs - the number of rows (and columns) in each block
2182 . rows - a concatenation of the rows for each block
2183 - v - a concatenation of logically two-dimensional arrays of values
2184 
2185   Level: advanced
2186 
2187   Note:
2188   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2189 
2190   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2191 
2192 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2193           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2194 @*/
2195 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2196 {
2197   PetscFunctionBegin;
2198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2199   PetscValidType(mat, 1);
2200   PetscValidIntPointer(rows, 4);
2201   PetscValidScalarPointer(v, 5);
2202   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2203 
2204   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2205   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2206   else {
2207     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2208   }
2209   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2210   PetscFunctionReturn(PETSC_SUCCESS);
2211 }
2212 
2213 /*@
2214    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2215    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2216    using a local (per-processor) numbering.
2217 
2218    Not Collective
2219 
2220    Input Parameters:
2221 +  x - the matrix
2222 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2223 -  cmapping - column mapping
2224 
2225    Level: intermediate
2226 
2227    Note:
2228    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2229 
2230 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2236   PetscValidType(x, 1);
2237   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2238   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2239   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2240   else {
2241     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2242     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2243   }
2244   PetscFunctionReturn(PETSC_SUCCESS);
2245 }
2246 
2247 /*@
2248    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2249 
2250    Not Collective
2251 
2252    Input Parameter:
2253 .  A - the matrix
2254 
2255    Output Parameters:
2256 + rmapping - row mapping
2257 - cmapping - column mapping
2258 
2259    Level: advanced
2260 
2261 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2262 @*/
2263 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2264 {
2265   PetscFunctionBegin;
2266   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2267   PetscValidType(A, 1);
2268   if (rmapping) {
2269     PetscValidPointer(rmapping, 2);
2270     *rmapping = A->rmap->mapping;
2271   }
2272   if (cmapping) {
2273     PetscValidPointer(cmapping, 3);
2274     *cmapping = A->cmap->mapping;
2275   }
2276   PetscFunctionReturn(PETSC_SUCCESS);
2277 }
2278 
2279 /*@
2280    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2281 
2282    Logically Collective
2283 
2284    Input Parameters:
2285 +  A - the matrix
2286 . rmap - row layout
2287 - cmap - column layout
2288 
2289    Level: advanced
2290 
2291    Note:
2292    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2293 
2294 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2295 @*/
2296 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2297 {
2298   PetscFunctionBegin;
2299   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2300   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2301   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2302   PetscFunctionReturn(PETSC_SUCCESS);
2303 }
2304 
2305 /*@
2306    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2307 
2308    Not Collective
2309 
2310    Input Parameter:
2311 .  A - the matrix
2312 
2313    Output Parameters:
2314 + rmap - row layout
2315 - cmap - column layout
2316 
2317    Level: advanced
2318 
2319 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2320 @*/
2321 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2322 {
2323   PetscFunctionBegin;
2324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2325   PetscValidType(A, 1);
2326   if (rmap) {
2327     PetscValidPointer(rmap, 2);
2328     *rmap = A->rmap;
2329   }
2330   if (cmap) {
2331     PetscValidPointer(cmap, 3);
2332     *cmap = A->cmap;
2333   }
2334   PetscFunctionReturn(PETSC_SUCCESS);
2335 }
2336 
2337 /*@C
2338    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2339    using a local numbering of the nodes.
2340 
2341    Not Collective
2342 
2343    Input Parameters:
2344 +  mat - the matrix
2345 .  nrow - number of rows
2346 .  irow - the row local indices
2347 .  ncol - number of columns
2348 .  icol - the column local indices
2349 .  y -  a logically two-dimensional array of values
2350 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2351 
2352    Level: intermediate
2353 
2354    Notes:
2355    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2356       `MatSetUp()` before using this routine
2357 
2358    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2359 
2360    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2361    options cannot be mixed without intervening calls to the assembly
2362    routines.
2363 
2364    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2365    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2366 
2367    Developer Note:
2368     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2369                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2370 
2371 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2372           `MatGetValuesLocal()`
2373 @*/
2374 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2375 {
2376   PetscFunctionBeginHot;
2377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2378   PetscValidType(mat, 1);
2379   MatCheckPreallocated(mat, 1);
2380   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2381   PetscValidIntPointer(irow, 3);
2382   PetscValidIntPointer(icol, 5);
2383   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2384   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2385   if (PetscDefined(USE_DEBUG)) {
2386     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2387     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2388   }
2389 
2390   if (mat->assembled) {
2391     mat->was_assembled = PETSC_TRUE;
2392     mat->assembled     = PETSC_FALSE;
2393   }
2394   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2395   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2396   else {
2397     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2398     const PetscInt *irowm, *icolm;
2399 
2400     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2401       bufr  = buf;
2402       bufc  = buf + nrow;
2403       irowm = bufr;
2404       icolm = bufc;
2405     } else {
2406       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2407       irowm = bufr;
2408       icolm = bufc;
2409     }
2410     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2411     else irowm = irow;
2412     if (mat->cmap->mapping) {
2413       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2414         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2415       } else icolm = irowm;
2416     } else icolm = icol;
2417     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2418     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2419   }
2420   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2421   PetscFunctionReturn(PETSC_SUCCESS);
2422 }
2423 
2424 /*@C
2425    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2426    using a local ordering of the nodes a block at a time.
2427 
2428    Not Collective
2429 
2430    Input Parameters:
2431 +  x - the matrix
2432 .  nrow - number of rows
2433 .  irow - the row local indices
2434 .  ncol - number of columns
2435 .  icol - the column local indices
2436 .  y -  a logically two-dimensional array of values
2437 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2438 
2439    Level: intermediate
2440 
2441    Notes:
2442    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2443       `MatSetUp()` before using this routine
2444 
2445    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2446       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2447 
2448    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2449    options cannot be mixed without intervening calls to the assembly
2450    routines.
2451 
2452    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2453    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2454 
2455    Developer Note:
2456     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2457                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2458 
2459 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2460           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2461 @*/
2462 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2463 {
2464   PetscFunctionBeginHot;
2465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2466   PetscValidType(mat, 1);
2467   MatCheckPreallocated(mat, 1);
2468   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2469   PetscValidIntPointer(irow, 3);
2470   PetscValidIntPointer(icol, 5);
2471   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2472   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2473   if (PetscDefined(USE_DEBUG)) {
2474     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2475     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);
2476   }
2477 
2478   if (mat->assembled) {
2479     mat->was_assembled = PETSC_TRUE;
2480     mat->assembled     = PETSC_FALSE;
2481   }
2482   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2483     PetscInt irbs, rbs;
2484     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2485     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2486     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2487   }
2488   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2489     PetscInt icbs, cbs;
2490     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2491     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2492     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2493   }
2494   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2495   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2496   else {
2497     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2498     const PetscInt *irowm, *icolm;
2499 
2500     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2501       bufr  = buf;
2502       bufc  = buf + nrow;
2503       irowm = bufr;
2504       icolm = bufc;
2505     } else {
2506       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2507       irowm = bufr;
2508       icolm = bufc;
2509     }
2510     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2511     else irowm = irow;
2512     if (mat->cmap->mapping) {
2513       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2514         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2515       } else icolm = irowm;
2516     } else icolm = icol;
2517     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2518     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2519   }
2520   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2521   PetscFunctionReturn(PETSC_SUCCESS);
2522 }
2523 
2524 /*@
2525    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2526 
2527    Collective
2528 
2529    Input Parameters:
2530 +  mat - the matrix
2531 -  x   - the vector to be multiplied
2532 
2533    Output Parameter:
2534 .  y - the result
2535 
2536    Level: developer
2537 
2538    Note:
2539    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2540    call `MatMultDiagonalBlock`(A,y,y).
2541 
2542 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2543 @*/
2544 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2545 {
2546   PetscFunctionBegin;
2547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2548   PetscValidType(mat, 1);
2549   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2550   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2551 
2552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2554   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2555   MatCheckPreallocated(mat, 1);
2556 
2557   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2558   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2559   PetscFunctionReturn(PETSC_SUCCESS);
2560 }
2561 
2562 /*@
2563    MatMult - Computes the matrix-vector product, y = Ax.
2564 
2565    Neighbor-wise Collective
2566 
2567    Input Parameters:
2568 +  mat - the matrix
2569 -  x   - the vector to be multiplied
2570 
2571    Output Parameter:
2572 .  y - the result
2573 
2574    Level: beginner
2575 
2576    Note:
2577    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2578    call `MatMult`(A,y,y).
2579 
2580 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2581 @*/
2582 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2583 {
2584   PetscFunctionBegin;
2585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2586   PetscValidType(mat, 1);
2587   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2588   VecCheckAssembled(x);
2589   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2592   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2593   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);
2594   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);
2595   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);
2596   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);
2597   PetscCall(VecSetErrorIfLocked(y, 3));
2598   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2599   MatCheckPreallocated(mat, 1);
2600 
2601   PetscCall(VecLockReadPush(x));
2602   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2603   PetscUseTypeMethod(mat, mult, x, y);
2604   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2605   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2606   PetscCall(VecLockReadPop(x));
2607   PetscFunctionReturn(PETSC_SUCCESS);
2608 }
2609 
2610 /*@
2611    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2612 
2613    Neighbor-wise Collective
2614 
2615    Input Parameters:
2616 +  mat - the matrix
2617 -  x   - the vector to be multiplied
2618 
2619    Output Parameter:
2620 .  y - the result
2621 
2622    Level: beginner
2623 
2624    Notes:
2625    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2626    call `MatMultTranspose`(A,y,y).
2627 
2628    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2629    use `MatMultHermitianTranspose()`
2630 
2631 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2632 @*/
2633 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2634 {
2635   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2636 
2637   PetscFunctionBegin;
2638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2639   PetscValidType(mat, 1);
2640   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2641   VecCheckAssembled(x);
2642   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2643 
2644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2646   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2647   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);
2648   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);
2649   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);
2650   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);
2651   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2652   MatCheckPreallocated(mat, 1);
2653 
2654   if (!mat->ops->multtranspose) {
2655     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2656     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);
2657   } else op = mat->ops->multtranspose;
2658   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2659   PetscCall(VecLockReadPush(x));
2660   PetscCall((*op)(mat, x, y));
2661   PetscCall(VecLockReadPop(x));
2662   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2663   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2664   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2665   PetscFunctionReturn(PETSC_SUCCESS);
2666 }
2667 
2668 /*@
2669    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2670 
2671    Neighbor-wise Collective
2672 
2673    Input Parameters:
2674 +  mat - the matrix
2675 -  x   - the vector to be multilplied
2676 
2677    Output Parameter:
2678 .  y - the result
2679 
2680    Level: beginner
2681 
2682    Notes:
2683    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2684    call `MatMultHermitianTranspose`(A,y,y).
2685 
2686    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2687 
2688    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2689 
2690 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2691 @*/
2692 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2693 {
2694   PetscFunctionBegin;
2695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2696   PetscValidType(mat, 1);
2697   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2698   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2699 
2700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2702   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2703   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);
2704   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);
2705   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);
2706   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);
2707   MatCheckPreallocated(mat, 1);
2708 
2709   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2710 #if defined(PETSC_USE_COMPLEX)
2711   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2712     PetscCall(VecLockReadPush(x));
2713     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2714     else PetscUseTypeMethod(mat, mult, x, y);
2715     PetscCall(VecLockReadPop(x));
2716   } else {
2717     Vec w;
2718     PetscCall(VecDuplicate(x, &w));
2719     PetscCall(VecCopy(x, w));
2720     PetscCall(VecConjugate(w));
2721     PetscCall(MatMultTranspose(mat, w, y));
2722     PetscCall(VecDestroy(&w));
2723     PetscCall(VecConjugate(y));
2724   }
2725   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2726 #else
2727   PetscCall(MatMultTranspose(mat, x, y));
2728 #endif
2729   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2730   PetscFunctionReturn(PETSC_SUCCESS);
2731 }
2732 
2733 /*@
2734     MatMultAdd -  Computes v3 = v2 + A * v1.
2735 
2736     Neighbor-wise Collective
2737 
2738     Input Parameters:
2739 +   mat - the matrix
2740 .   v1 - the vector to be multiplied by `mat`
2741 -   v2 - the vector to be added to the result
2742 
2743     Output Parameter:
2744 .   v3 - the result
2745 
2746     Level: beginner
2747 
2748     Note:
2749     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2750     call `MatMultAdd`(A,v1,v2,v1).
2751 
2752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2753 @*/
2754 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2755 {
2756   PetscFunctionBegin;
2757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2758   PetscValidType(mat, 1);
2759   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2760   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2761   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2762 
2763   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2764   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2765   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);
2766   /* 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);
2767      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); */
2768   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);
2769   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);
2770   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2771   MatCheckPreallocated(mat, 1);
2772 
2773   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2774   PetscCall(VecLockReadPush(v1));
2775   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2776   PetscCall(VecLockReadPop(v1));
2777   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2778   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2779   PetscFunctionReturn(PETSC_SUCCESS);
2780 }
2781 
2782 /*@
2783    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2784 
2785    Neighbor-wise Collective
2786 
2787    Input Parameters:
2788 +  mat - the matrix
2789 .  v1 - the vector to be multiplied by the transpose of the matrix
2790 -  v2 - the vector to be added to the result
2791 
2792    Output Parameter:
2793 .  v3 - the result
2794 
2795    Level: beginner
2796 
2797    Note:
2798    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2799    call `MatMultTransposeAdd`(A,v1,v2,v1).
2800 
2801 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2802 @*/
2803 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2804 {
2805   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2806 
2807   PetscFunctionBegin;
2808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2809   PetscValidType(mat, 1);
2810   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2811   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2812   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2813 
2814   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2815   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2816   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);
2817   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);
2818   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);
2819   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2820   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2821   MatCheckPreallocated(mat, 1);
2822 
2823   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2824   PetscCall(VecLockReadPush(v1));
2825   PetscCall((*op)(mat, v1, v2, v3));
2826   PetscCall(VecLockReadPop(v1));
2827   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2828   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2829   PetscFunctionReturn(PETSC_SUCCESS);
2830 }
2831 
2832 /*@
2833    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2834 
2835    Neighbor-wise Collective
2836 
2837    Input Parameters:
2838 +  mat - the matrix
2839 .  v1 - the vector to be multiplied by the Hermitian transpose
2840 -  v2 - the vector to be added to the result
2841 
2842    Output Parameter:
2843 .  v3 - the result
2844 
2845    Level: beginner
2846 
2847    Note:
2848    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2849    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2850 
2851 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2852 @*/
2853 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2854 {
2855   PetscFunctionBegin;
2856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2857   PetscValidType(mat, 1);
2858   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2859   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2860   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2861 
2862   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2863   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2864   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2865   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);
2866   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);
2867   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);
2868   MatCheckPreallocated(mat, 1);
2869 
2870   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2871   PetscCall(VecLockReadPush(v1));
2872   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2873   else {
2874     Vec w, z;
2875     PetscCall(VecDuplicate(v1, &w));
2876     PetscCall(VecCopy(v1, w));
2877     PetscCall(VecConjugate(w));
2878     PetscCall(VecDuplicate(v3, &z));
2879     PetscCall(MatMultTranspose(mat, w, z));
2880     PetscCall(VecDestroy(&w));
2881     PetscCall(VecConjugate(z));
2882     if (v2 != v3) {
2883       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2884     } else {
2885       PetscCall(VecAXPY(v3, 1.0, z));
2886     }
2887     PetscCall(VecDestroy(&z));
2888   }
2889   PetscCall(VecLockReadPop(v1));
2890   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2891   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2892   PetscFunctionReturn(PETSC_SUCCESS);
2893 }
2894 
2895 /*@C
2896    MatGetFactorType - gets the type of factorization it is
2897 
2898    Not Collective
2899 
2900    Input Parameter:
2901 .  mat - the matrix
2902 
2903    Output Parameter:
2904 .  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`
2905 
2906    Level: intermediate
2907 
2908 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2909           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2910 @*/
2911 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2912 {
2913   PetscFunctionBegin;
2914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2915   PetscValidType(mat, 1);
2916   PetscValidPointer(t, 2);
2917   *t = mat->factortype;
2918   PetscFunctionReturn(PETSC_SUCCESS);
2919 }
2920 
2921 /*@C
2922    MatSetFactorType - sets the type of factorization it is
2923 
2924    Logically Collective
2925 
2926    Input Parameters:
2927 +  mat - the matrix
2928 -  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`
2929 
2930    Level: intermediate
2931 
2932 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2933           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2934 @*/
2935 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2936 {
2937   PetscFunctionBegin;
2938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2939   PetscValidType(mat, 1);
2940   mat->factortype = t;
2941   PetscFunctionReturn(PETSC_SUCCESS);
2942 }
2943 
2944 /*@C
2945    MatGetInfo - Returns information about matrix storage (number of
2946    nonzeros, memory, etc.).
2947 
2948    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2949 
2950    Input Parameters:
2951 +  mat - the matrix
2952 -  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)
2953 
2954    Output Parameter:
2955 .  info - matrix information context
2956 
2957    Options Database Key:
2958 .  -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2959 
2960    Notes:
2961    The `MatInfo` context contains a variety of matrix data, including
2962    number of nonzeros allocated and used, number of mallocs during
2963    matrix assembly, etc.  Additional information for factored matrices
2964    is provided (such as the fill ratio, number of mallocs during
2965    factorization, etc.).
2966 
2967    Example:
2968    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2969    data within the MatInfo context.  For example,
2970 .vb
2971       MatInfo info;
2972       Mat     A;
2973       double  mal, nz_a, nz_u;
2974 
2975       MatGetInfo(A, MAT_LOCAL, &info);
2976       mal  = info.mallocs;
2977       nz_a = info.nz_allocated;
2978 .ve
2979 
2980    Fortran users should declare info as a double precision
2981    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2982    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2983    a complete list of parameter names.
2984 .vb
2985       double  precision info(MAT_INFO_SIZE)
2986       double  precision mal, nz_a
2987       Mat     A
2988       integer ierr
2989 
2990       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2991       mal = info(MAT_INFO_MALLOCS)
2992       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2993 .ve
2994 
2995     Level: intermediate
2996 
2997     Developer Note:
2998     The Fortran interface is not autogenerated as the
2999     interface definition cannot be generated correctly [due to `MatInfo` argument]
3000 
3001 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3002 @*/
3003 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3004 {
3005   PetscFunctionBegin;
3006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3007   PetscValidType(mat, 1);
3008   PetscValidPointer(info, 3);
3009   MatCheckPreallocated(mat, 1);
3010   PetscUseTypeMethod(mat, getinfo, flag, info);
3011   PetscFunctionReturn(PETSC_SUCCESS);
3012 }
3013 
3014 /*
3015    This is used by external packages where it is not easy to get the info from the actual
3016    matrix factorization.
3017 */
3018 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3019 {
3020   PetscFunctionBegin;
3021   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3022   PetscFunctionReturn(PETSC_SUCCESS);
3023 }
3024 
3025 /*@C
3026    MatLUFactor - Performs in-place LU factorization of matrix.
3027 
3028    Collective
3029 
3030    Input Parameters:
3031 +  mat - the matrix
3032 .  row - row permutation
3033 .  col - column permutation
3034 -  info - options for factorization, includes
3035 .vb
3036           fill - expected fill as ratio of original fill.
3037           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3038                    Run with the option -info to determine an optimal value to use
3039 .ve
3040    Level: developer
3041 
3042    Notes:
3043    Most users should employ the `KSP` interface for linear solvers
3044    instead of working directly with matrix algebra routines such as this.
3045    See, e.g., `KSPCreate()`.
3046 
3047    This changes the state of the matrix to a factored matrix; it cannot be used
3048    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3049 
3050    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3051    when not using `KSP`.
3052 
3053    Developer Note:
3054    The Fortran interface is not autogenerated as the
3055    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3056 
3057 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3058           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3059 @*/
3060 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3061 {
3062   MatFactorInfo tinfo;
3063 
3064   PetscFunctionBegin;
3065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3066   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3067   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3068   if (info) PetscValidPointer(info, 4);
3069   PetscValidType(mat, 1);
3070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3071   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3072   MatCheckPreallocated(mat, 1);
3073   if (!info) {
3074     PetscCall(MatFactorInfoInitialize(&tinfo));
3075     info = &tinfo;
3076   }
3077 
3078   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3079   PetscUseTypeMethod(mat, lufactor, row, col, info);
3080   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3081   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3082   PetscFunctionReturn(PETSC_SUCCESS);
3083 }
3084 
3085 /*@C
3086    MatILUFactor - Performs in-place ILU factorization of matrix.
3087 
3088    Collective
3089 
3090    Input Parameters:
3091 +  mat - the matrix
3092 .  row - row permutation
3093 .  col - column permutation
3094 -  info - structure containing
3095 .vb
3096       levels - number of levels of fill.
3097       expected fill - as ratio of original fill.
3098       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3099                 missing diagonal entries)
3100 .ve
3101 
3102    Level: developer
3103 
3104    Notes:
3105    Most users should employ the `KSP` interface for linear solvers
3106    instead of working directly with matrix algebra routines such as this.
3107    See, e.g., `KSPCreate()`.
3108 
3109    Probably really in-place only when level of fill is zero, otherwise allocates
3110    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3111    when not using `KSP`.
3112 
3113    Developer Note:
3114    The Fortran interface is not autogenerated as the
3115    interface definition cannot be generated correctly [due to MatFactorInfo]
3116 
3117 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3118 @*/
3119 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3120 {
3121   PetscFunctionBegin;
3122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3123   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3124   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3125   PetscValidPointer(info, 4);
3126   PetscValidType(mat, 1);
3127   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3129   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3130   MatCheckPreallocated(mat, 1);
3131 
3132   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3133   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3134   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3135   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3136   PetscFunctionReturn(PETSC_SUCCESS);
3137 }
3138 
3139 /*@C
3140    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3141    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3142 
3143    Collective
3144 
3145    Input Parameters:
3146 +  fact - the factor matrix obtained with `MatGetFactor()`
3147 .  mat - the matrix
3148 .  row - the row permutation
3149 .  col - the column permutation
3150 -  info - options for factorization, includes
3151 .vb
3152           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3153           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3154 .ve
3155 
3156    Level: developer
3157 
3158    Notes:
3159     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3160 
3161    Most users should employ the simplified `KSP` interface for linear solvers
3162    instead of working directly with matrix algebra routines such as this.
3163    See, e.g., `KSPCreate()`.
3164 
3165    Developer Note:
3166    The Fortran interface is not autogenerated as the
3167    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3168 
3169 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3170 @*/
3171 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3172 {
3173   MatFactorInfo tinfo;
3174 
3175   PetscFunctionBegin;
3176   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3178   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3179   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3180   if (info) PetscValidPointer(info, 5);
3181   PetscValidType(fact, 1);
3182   PetscValidType(mat, 2);
3183   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3184   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3185   MatCheckPreallocated(mat, 2);
3186   if (!info) {
3187     PetscCall(MatFactorInfoInitialize(&tinfo));
3188     info = &tinfo;
3189   }
3190 
3191   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3192   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3193   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3194   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3195   PetscFunctionReturn(PETSC_SUCCESS);
3196 }
3197 
3198 /*@C
3199    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3200    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3201 
3202    Collective
3203 
3204    Input Parameters:
3205 +  fact - the factor matrix obtained with `MatGetFactor()`
3206 .  mat - the matrix
3207 -  info - options for factorization
3208 
3209    Level: developer
3210 
3211    Notes:
3212    See `MatLUFactor()` for in-place factorization.  See
3213    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3214 
3215    Most users should employ the `KSP` interface for linear solvers
3216    instead of working directly with matrix algebra routines such as this.
3217    See, e.g., `KSPCreate()`.
3218 
3219     Developer Note:
3220     The Fortran interface is not autogenerated as the
3221     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3222 
3223 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3224 @*/
3225 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3226 {
3227   MatFactorInfo tinfo;
3228 
3229   PetscFunctionBegin;
3230   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3231   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3232   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3233   PetscValidType(fact, 1);
3234   PetscValidType(mat, 2);
3235   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3236   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,
3237              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3238 
3239   MatCheckPreallocated(mat, 2);
3240   if (!info) {
3241     PetscCall(MatFactorInfoInitialize(&tinfo));
3242     info = &tinfo;
3243   }
3244 
3245   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3246   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3247   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3248   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3249   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3250   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3251   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3252   PetscFunctionReturn(PETSC_SUCCESS);
3253 }
3254 
3255 /*@C
3256    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3257    symmetric matrix.
3258 
3259    Collective
3260 
3261    Input Parameters:
3262 +  mat - the matrix
3263 .  perm - row and column permutations
3264 -  f - expected fill as ratio of original fill
3265 
3266    Level: developer
3267 
3268    Notes:
3269    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3270    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3271 
3272    Most users should employ the `KSP` interface for linear solvers
3273    instead of working directly with matrix algebra routines such as this.
3274    See, e.g., `KSPCreate()`.
3275 
3276    Developer Note:
3277    The Fortran interface is not autogenerated as the
3278    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3279 
3280 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3281           `MatGetOrdering()`
3282 @*/
3283 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3284 {
3285   MatFactorInfo tinfo;
3286 
3287   PetscFunctionBegin;
3288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3289   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3290   if (info) PetscValidPointer(info, 3);
3291   PetscValidType(mat, 1);
3292   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3293   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3294   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3295   MatCheckPreallocated(mat, 1);
3296   if (!info) {
3297     PetscCall(MatFactorInfoInitialize(&tinfo));
3298     info = &tinfo;
3299   }
3300 
3301   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3302   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3303   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3304   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3305   PetscFunctionReturn(PETSC_SUCCESS);
3306 }
3307 
3308 /*@C
3309    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3310    of a symmetric matrix.
3311 
3312    Collective
3313 
3314    Input Parameters:
3315 +  fact - the factor matrix obtained with `MatGetFactor()`
3316 .  mat - the matrix
3317 .  perm - row and column permutations
3318 -  info - options for factorization, includes
3319 .vb
3320           fill - expected fill as ratio of original fill.
3321           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3322                    Run with the option -info to determine an optimal value to use
3323 .ve
3324 
3325    Level: developer
3326 
3327    Notes:
3328    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3329    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3330 
3331    Most users should employ the `KSP` interface for linear solvers
3332    instead of working directly with matrix algebra routines such as this.
3333    See, e.g., `KSPCreate()`.
3334 
3335    Developer Note:
3336    The Fortran interface is not autogenerated as the
3337    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3338 
3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3340           `MatGetOrdering()`
3341 @*/
3342 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3343 {
3344   MatFactorInfo tinfo;
3345 
3346   PetscFunctionBegin;
3347   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3349   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3350   if (info) PetscValidPointer(info, 4);
3351   PetscValidType(fact, 1);
3352   PetscValidType(mat, 2);
3353   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3354   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3355   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3356   MatCheckPreallocated(mat, 2);
3357   if (!info) {
3358     PetscCall(MatFactorInfoInitialize(&tinfo));
3359     info = &tinfo;
3360   }
3361 
3362   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3363   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3364   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3365   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3366   PetscFunctionReturn(PETSC_SUCCESS);
3367 }
3368 
3369 /*@C
3370    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3371    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3372    `MatCholeskyFactorSymbolic()`.
3373 
3374    Collective
3375 
3376    Input Parameters:
3377 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3378 .  mat - the initial matrix that is to be factored
3379 -  info - options for factorization
3380 
3381    Level: developer
3382 
3383    Note:
3384    Most users should employ the `KSP` interface for linear solvers
3385    instead of working directly with matrix algebra routines such as this.
3386    See, e.g., `KSPCreate()`.
3387 
3388    Developer Note:
3389    The Fortran interface is not autogenerated as the
3390    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3391 
3392 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3393 @*/
3394 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3395 {
3396   MatFactorInfo tinfo;
3397 
3398   PetscFunctionBegin;
3399   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3401   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3402   PetscValidType(fact, 1);
3403   PetscValidType(mat, 2);
3404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3405   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,
3406              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3407   MatCheckPreallocated(mat, 2);
3408   if (!info) {
3409     PetscCall(MatFactorInfoInitialize(&tinfo));
3410     info = &tinfo;
3411   }
3412 
3413   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3414   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3415   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3416   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3417   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3418   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3419   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3420   PetscFunctionReturn(PETSC_SUCCESS);
3421 }
3422 
3423 /*@
3424    MatQRFactor - Performs in-place QR factorization of matrix.
3425 
3426    Collective
3427 
3428    Input Parameters:
3429 +  mat - the matrix
3430 .  col - column permutation
3431 -  info - options for factorization, includes
3432 .vb
3433           fill - expected fill as ratio of original fill.
3434           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3435                    Run with the option -info to determine an optimal value to use
3436 .ve
3437 
3438    Level: developer
3439 
3440    Notes:
3441    Most users should employ the `KSP` interface for linear solvers
3442    instead of working directly with matrix algebra routines such as this.
3443    See, e.g., `KSPCreate()`.
3444 
3445    This changes the state of the matrix to a factored matrix; it cannot be used
3446    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3447 
3448    Developer Note:
3449    The Fortran interface is not autogenerated as the
3450    interface definition cannot be generated correctly [due to MatFactorInfo]
3451 
3452 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3453           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3454 @*/
3455 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3456 {
3457   PetscFunctionBegin;
3458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3459   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3460   if (info) PetscValidPointer(info, 3);
3461   PetscValidType(mat, 1);
3462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3464   MatCheckPreallocated(mat, 1);
3465   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3466   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3467   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3468   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3469   PetscFunctionReturn(PETSC_SUCCESS);
3470 }
3471 
3472 /*@
3473    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3474    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3475 
3476    Collective
3477 
3478    Input Parameters:
3479 +  fact - the factor matrix obtained with `MatGetFactor()`
3480 .  mat - the matrix
3481 .  col - column permutation
3482 -  info - options for factorization, includes
3483 .vb
3484           fill - expected fill as ratio of original fill.
3485           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3486                    Run with the option -info to determine an optimal value to use
3487 .ve
3488 
3489    Level: developer
3490 
3491    Note:
3492    Most users should employ the `KSP` interface for linear solvers
3493    instead of working directly with matrix algebra routines such as this.
3494    See, e.g., `KSPCreate()`.
3495 
3496    Developer Note:
3497    The Fortran interface is not autogenerated as the
3498    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3499 
3500 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3501 @*/
3502 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3503 {
3504   MatFactorInfo tinfo;
3505 
3506   PetscFunctionBegin;
3507   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3509   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3510   if (info) PetscValidPointer(info, 4);
3511   PetscValidType(fact, 1);
3512   PetscValidType(mat, 2);
3513   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3514   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3515   MatCheckPreallocated(mat, 2);
3516   if (!info) {
3517     PetscCall(MatFactorInfoInitialize(&tinfo));
3518     info = &tinfo;
3519   }
3520 
3521   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3522   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3523   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3524   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3525   PetscFunctionReturn(PETSC_SUCCESS);
3526 }
3527 
3528 /*@
3529    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3530    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3531 
3532    Collective
3533 
3534    Input Parameters:
3535 +  fact - the factor matrix obtained with `MatGetFactor()`
3536 .  mat - the matrix
3537 -  info - options for factorization
3538 
3539    Level: developer
3540 
3541    Notes:
3542    See `MatQRFactor()` for in-place factorization.
3543 
3544    Most users should employ the `KSP` interface for linear solvers
3545    instead of working directly with matrix algebra routines such as this.
3546    See, e.g., `KSPCreate()`.
3547 
3548    Developer Note:
3549    The Fortran interface is not autogenerated as the
3550    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3551 
3552 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3553 @*/
3554 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3555 {
3556   MatFactorInfo tinfo;
3557 
3558   PetscFunctionBegin;
3559   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3561   PetscValidType(fact, 1);
3562   PetscValidType(mat, 2);
3563   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3564   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,
3565              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3566 
3567   MatCheckPreallocated(mat, 2);
3568   if (!info) {
3569     PetscCall(MatFactorInfoInitialize(&tinfo));
3570     info = &tinfo;
3571   }
3572 
3573   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3574   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3575   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3576   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3577   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3578   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3579   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3580   PetscFunctionReturn(PETSC_SUCCESS);
3581 }
3582 
3583 /*@
3584    MatSolve - Solves A x = b, given a factored matrix.
3585 
3586    Neighbor-wise Collective
3587 
3588    Input Parameters:
3589 +  mat - the factored matrix
3590 -  b - the right-hand-side vector
3591 
3592    Output Parameter:
3593 .  x - the result vector
3594 
3595    Level: developer
3596 
3597    Notes:
3598    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3599    call `MatSolve`(A,x,x).
3600 
3601    Most users should employ the `KSP` interface for linear solvers
3602    instead of working directly with matrix algebra routines such as this.
3603    See, e.g., `KSPCreate()`.
3604 
3605 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3606 @*/
3607 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3608 {
3609   PetscFunctionBegin;
3610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3611   PetscValidType(mat, 1);
3612   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3613   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3614   PetscCheckSameComm(mat, 1, b, 2);
3615   PetscCheckSameComm(mat, 1, x, 3);
3616   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3617   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);
3618   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);
3619   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);
3620   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3621   MatCheckPreallocated(mat, 1);
3622 
3623   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3624   if (mat->factorerrortype) {
3625     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3626     PetscCall(VecSetInf(x));
3627   } else PetscUseTypeMethod(mat, solve, b, x);
3628   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3629   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3630   PetscFunctionReturn(PETSC_SUCCESS);
3631 }
3632 
3633 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3634 {
3635   Vec      b, x;
3636   PetscInt N, i;
3637   PetscErrorCode (*f)(Mat, Vec, Vec);
3638   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3639 
3640   PetscFunctionBegin;
3641   if (A->factorerrortype) {
3642     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3643     PetscCall(MatSetInf(X));
3644     PetscFunctionReturn(PETSC_SUCCESS);
3645   }
3646   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3647   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3648   PetscCall(MatBoundToCPU(A, &Abound));
3649   if (!Abound) {
3650     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3651     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3652   }
3653 #if PetscDefined(HAVE_CUDA)
3654   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3655   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3656 #elif PetscDefined(HAVE_HIP)
3657   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3658   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3659 #endif
3660   PetscCall(MatGetSize(B, NULL, &N));
3661   for (i = 0; i < N; i++) {
3662     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3663     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3664     PetscCall((*f)(A, b, x));
3665     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3666     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3667   }
3668   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3669   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3670   PetscFunctionReturn(PETSC_SUCCESS);
3671 }
3672 
3673 /*@
3674    MatMatSolve - Solves A X = B, given a factored matrix.
3675 
3676    Neighbor-wise Collective
3677 
3678    Input Parameters:
3679 +  A - the factored matrix
3680 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3681 
3682    Output Parameter:
3683 .  X - the result matrix (dense matrix)
3684 
3685    Level: developer
3686 
3687    Note:
3688    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3689    otherwise, `B` and `X` cannot be the same.
3690 
3691 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3692 @*/
3693 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3694 {
3695   PetscFunctionBegin;
3696   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3697   PetscValidType(A, 1);
3698   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3699   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3700   PetscCheckSameComm(A, 1, B, 2);
3701   PetscCheckSameComm(A, 1, X, 3);
3702   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);
3703   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);
3704   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");
3705   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3706   MatCheckPreallocated(A, 1);
3707 
3708   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3709   if (!A->ops->matsolve) {
3710     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3711     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3712   } else PetscUseTypeMethod(A, matsolve, B, X);
3713   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3714   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3715   PetscFunctionReturn(PETSC_SUCCESS);
3716 }
3717 
3718 /*@
3719    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3720 
3721    Neighbor-wise Collective
3722 
3723    Input Parameters:
3724 +  A - the factored matrix
3725 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3726 
3727    Output Parameter:
3728 .  X - the result matrix (dense matrix)
3729 
3730    Level: developer
3731 
3732    Note:
3733    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3734    call `MatMatSolveTranspose`(A,X,X).
3735 
3736 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3737 @*/
3738 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3739 {
3740   PetscFunctionBegin;
3741   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3742   PetscValidType(A, 1);
3743   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3744   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3745   PetscCheckSameComm(A, 1, B, 2);
3746   PetscCheckSameComm(A, 1, X, 3);
3747   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3748   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);
3749   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);
3750   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);
3751   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");
3752   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3753   MatCheckPreallocated(A, 1);
3754 
3755   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3756   if (!A->ops->matsolvetranspose) {
3757     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3758     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3759   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3760   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3761   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3762   PetscFunctionReturn(PETSC_SUCCESS);
3763 }
3764 
3765 /*@
3766    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3767 
3768    Neighbor-wise Collective
3769 
3770    Input Parameters:
3771 +  A - the factored matrix
3772 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3773 
3774    Output Parameter:
3775 .  X - the result matrix (dense matrix)
3776 
3777    Level: developer
3778 
3779    Note:
3780    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
3781    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3782 
3783 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3784 @*/
3785 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3786 {
3787   PetscFunctionBegin;
3788   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3789   PetscValidType(A, 1);
3790   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3791   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3792   PetscCheckSameComm(A, 1, Bt, 2);
3793   PetscCheckSameComm(A, 1, X, 3);
3794 
3795   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3796   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);
3797   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);
3798   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");
3799   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3800   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3801   MatCheckPreallocated(A, 1);
3802 
3803   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3804   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3805   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3806   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3807   PetscFunctionReturn(PETSC_SUCCESS);
3808 }
3809 
3810 /*@
3811    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3812                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3813 
3814    Neighbor-wise Collective
3815 
3816    Input Parameters:
3817 +  mat - the factored matrix
3818 -  b - the right-hand-side vector
3819 
3820    Output Parameter:
3821 .  x - the result vector
3822 
3823    Level: developer
3824 
3825    Notes:
3826    `MatSolve()` should be used for most applications, as it performs
3827    a forward solve followed by a backward solve.
3828 
3829    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3830    call `MatForwardSolve`(A,x,x).
3831 
3832    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3833    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3834    `MatForwardSolve()` solves U^T*D y = b, and
3835    `MatBackwardSolve()` solves U x = y.
3836    Thus they do not provide a symmetric preconditioner.
3837 
3838 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3839 @*/
3840 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3841 {
3842   PetscFunctionBegin;
3843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3844   PetscValidType(mat, 1);
3845   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3846   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3847   PetscCheckSameComm(mat, 1, b, 2);
3848   PetscCheckSameComm(mat, 1, x, 3);
3849   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3850   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);
3851   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);
3852   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);
3853   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3854   MatCheckPreallocated(mat, 1);
3855 
3856   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3857   PetscUseTypeMethod(mat, forwardsolve, b, x);
3858   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3859   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3860   PetscFunctionReturn(PETSC_SUCCESS);
3861 }
3862 
3863 /*@
3864    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3865                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3866 
3867    Neighbor-wise Collective
3868 
3869    Input Parameters:
3870 +  mat - the factored matrix
3871 -  b - the right-hand-side vector
3872 
3873    Output Parameter:
3874 .  x - the result vector
3875 
3876    Level: developer
3877 
3878    Notes:
3879    `MatSolve()` should be used for most applications, as it performs
3880    a forward solve followed by a backward solve.
3881 
3882    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3883    call `MatBackwardSolve`(A,x,x).
3884 
3885    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3886    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3887    `MatForwardSolve()` solves U^T*D y = b, and
3888    `MatBackwardSolve()` solves U x = y.
3889    Thus they do not provide a symmetric preconditioner.
3890 
3891 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3892 @*/
3893 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3894 {
3895   PetscFunctionBegin;
3896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3897   PetscValidType(mat, 1);
3898   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3899   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3900   PetscCheckSameComm(mat, 1, b, 2);
3901   PetscCheckSameComm(mat, 1, x, 3);
3902   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3903   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);
3904   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);
3905   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);
3906   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3907   MatCheckPreallocated(mat, 1);
3908 
3909   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3910   PetscUseTypeMethod(mat, backwardsolve, b, x);
3911   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3912   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3913   PetscFunctionReturn(PETSC_SUCCESS);
3914 }
3915 
3916 /*@
3917    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3918 
3919    Neighbor-wise Collective
3920 
3921    Input Parameters:
3922 +  mat - the factored matrix
3923 .  b - the right-hand-side vector
3924 -  y - the vector to be added to
3925 
3926    Output Parameter:
3927 .  x - the result vector
3928 
3929    Level: developer
3930 
3931    Note:
3932    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3933    call `MatSolveAdd`(A,x,y,x).
3934 
3935 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3936 @*/
3937 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3938 {
3939   PetscScalar one = 1.0;
3940   Vec         tmp;
3941 
3942   PetscFunctionBegin;
3943   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3944   PetscValidType(mat, 1);
3945   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3946   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3947   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3948   PetscCheckSameComm(mat, 1, b, 2);
3949   PetscCheckSameComm(mat, 1, y, 3);
3950   PetscCheckSameComm(mat, 1, x, 4);
3951   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3952   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);
3953   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);
3954   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);
3955   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);
3956   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);
3957   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3958   MatCheckPreallocated(mat, 1);
3959 
3960   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3961   if (mat->factorerrortype) {
3962     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3963     PetscCall(VecSetInf(x));
3964   } else if (mat->ops->solveadd) {
3965     PetscUseTypeMethod(mat, solveadd, b, y, x);
3966   } else {
3967     /* do the solve then the add manually */
3968     if (x != y) {
3969       PetscCall(MatSolve(mat, b, x));
3970       PetscCall(VecAXPY(x, one, y));
3971     } else {
3972       PetscCall(VecDuplicate(x, &tmp));
3973       PetscCall(VecCopy(x, tmp));
3974       PetscCall(MatSolve(mat, b, x));
3975       PetscCall(VecAXPY(x, one, tmp));
3976       PetscCall(VecDestroy(&tmp));
3977     }
3978   }
3979   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3980   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3981   PetscFunctionReturn(PETSC_SUCCESS);
3982 }
3983 
3984 /*@
3985    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3986 
3987    Neighbor-wise Collective
3988 
3989    Input Parameters:
3990 +  mat - the factored matrix
3991 -  b - the right-hand-side vector
3992 
3993    Output Parameter:
3994 .  x - the result vector
3995 
3996    Level: developer
3997 
3998    Notes:
3999    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4000    call `MatSolveTranspose`(A,x,x).
4001 
4002    Most users should employ the `KSP` interface for linear solvers
4003    instead of working directly with matrix algebra routines such as this.
4004    See, e.g., `KSPCreate()`.
4005 
4006 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4007 @*/
4008 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4009 {
4010   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4011 
4012   PetscFunctionBegin;
4013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4014   PetscValidType(mat, 1);
4015   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4016   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4017   PetscCheckSameComm(mat, 1, b, 2);
4018   PetscCheckSameComm(mat, 1, x, 3);
4019   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4020   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);
4021   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);
4022   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4023   MatCheckPreallocated(mat, 1);
4024   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4025   if (mat->factorerrortype) {
4026     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4027     PetscCall(VecSetInf(x));
4028   } else {
4029     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4030     PetscCall((*f)(mat, b, x));
4031   }
4032   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4033   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4034   PetscFunctionReturn(PETSC_SUCCESS);
4035 }
4036 
4037 /*@
4038    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4039                       factored matrix.
4040 
4041    Neighbor-wise Collective
4042 
4043    Input Parameters:
4044 +  mat - the factored matrix
4045 .  b - the right-hand-side vector
4046 -  y - the vector to be added to
4047 
4048    Output Parameter:
4049 .  x - the result vector
4050 
4051    Level: developer
4052 
4053    Note:
4054    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4055    call `MatSolveTransposeAdd`(A,x,y,x).
4056 
4057 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4058 @*/
4059 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4060 {
4061   PetscScalar one = 1.0;
4062   Vec         tmp;
4063   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4064 
4065   PetscFunctionBegin;
4066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4067   PetscValidType(mat, 1);
4068   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4069   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4070   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4071   PetscCheckSameComm(mat, 1, b, 2);
4072   PetscCheckSameComm(mat, 1, y, 3);
4073   PetscCheckSameComm(mat, 1, x, 4);
4074   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4075   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);
4076   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);
4077   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);
4078   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);
4079   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4080   MatCheckPreallocated(mat, 1);
4081 
4082   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4083   if (mat->factorerrortype) {
4084     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4085     PetscCall(VecSetInf(x));
4086   } else if (f) {
4087     PetscCall((*f)(mat, b, y, x));
4088   } else {
4089     /* do the solve then the add manually */
4090     if (x != y) {
4091       PetscCall(MatSolveTranspose(mat, b, x));
4092       PetscCall(VecAXPY(x, one, y));
4093     } else {
4094       PetscCall(VecDuplicate(x, &tmp));
4095       PetscCall(VecCopy(x, tmp));
4096       PetscCall(MatSolveTranspose(mat, b, x));
4097       PetscCall(VecAXPY(x, one, tmp));
4098       PetscCall(VecDestroy(&tmp));
4099     }
4100   }
4101   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4102   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4103   PetscFunctionReturn(PETSC_SUCCESS);
4104 }
4105 
4106 /*@
4107    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4108 
4109    Neighbor-wise Collective
4110 
4111    Input Parameters:
4112 +  mat - the matrix
4113 .  b - the right hand side
4114 .  omega - the relaxation factor
4115 .  flag - flag indicating the type of SOR (see below)
4116 .  shift -  diagonal shift
4117 .  its - the number of iterations
4118 -  lits - the number of local iterations
4119 
4120    Output Parameter:
4121 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4122 
4123    SOR Flags:
4124 +     `SOR_FORWARD_SWEEP` - forward SOR
4125 .     `SOR_BACKWARD_SWEEP` - backward SOR
4126 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4127 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4128 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4129 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4130 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4131 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4132          upper/lower triangular part of matrix to
4133          vector (with omega)
4134 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4135 
4136    Level: developer
4137 
4138    Notes:
4139    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4140    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4141    on each processor.
4142 
4143    Application programmers will not generally use `MatSOR()` directly,
4144    but instead will employ the `KSP`/`PC` interface.
4145 
4146    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4147 
4148    Most users should employ the `KSP` interface for linear solvers
4149    instead of working directly with matrix algebra routines such as this.
4150    See, e.g., `KSPCreate()`.
4151 
4152    Vectors `x` and `b` CANNOT be the same
4153 
4154    The flags are implemented as bitwise inclusive or operations.
4155    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4156    to specify a zero initial guess for SSOR.
4157 
4158    Developer Note:
4159    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4160 
4161 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4162 @*/
4163 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4164 {
4165   PetscFunctionBegin;
4166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4167   PetscValidType(mat, 1);
4168   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4169   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4170   PetscCheckSameComm(mat, 1, b, 2);
4171   PetscCheckSameComm(mat, 1, x, 8);
4172   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4173   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4174   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);
4175   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);
4176   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);
4177   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4178   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4179   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4180 
4181   MatCheckPreallocated(mat, 1);
4182   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4183   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4184   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4185   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4186   PetscFunctionReturn(PETSC_SUCCESS);
4187 }
4188 
4189 /*
4190       Default matrix copy routine.
4191 */
4192 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4193 {
4194   PetscInt           i, rstart = 0, rend = 0, nz;
4195   const PetscInt    *cwork;
4196   const PetscScalar *vwork;
4197 
4198   PetscFunctionBegin;
4199   if (B->assembled) PetscCall(MatZeroEntries(B));
4200   if (str == SAME_NONZERO_PATTERN) {
4201     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4202     for (i = rstart; i < rend; i++) {
4203       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4204       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4205       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4206     }
4207   } else {
4208     PetscCall(MatAYPX(B, 0.0, A, str));
4209   }
4210   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4211   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4212   PetscFunctionReturn(PETSC_SUCCESS);
4213 }
4214 
4215 /*@
4216    MatCopy - Copies a matrix to another matrix.
4217 
4218    Collective
4219 
4220    Input Parameters:
4221 +  A - the matrix
4222 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4223 
4224    Output Parameter:
4225 .  B - where the copy is put
4226 
4227    Level: intermediate
4228 
4229    Notes:
4230    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4231 
4232    `MatCopy()` copies the matrix entries of a matrix to another existing
4233    matrix (after first zeroing the second matrix).  A related routine is
4234    `MatConvert()`, which first creates a new matrix and then copies the data.
4235 
4236 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4237 @*/
4238 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4239 {
4240   PetscInt i;
4241 
4242   PetscFunctionBegin;
4243   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4244   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4245   PetscValidType(A, 1);
4246   PetscValidType(B, 2);
4247   PetscCheckSameComm(A, 1, B, 2);
4248   MatCheckPreallocated(B, 2);
4249   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4250   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4251   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,
4252              A->cmap->N, B->cmap->N);
4253   MatCheckPreallocated(A, 1);
4254   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4255 
4256   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4257   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4258   else PetscCall(MatCopy_Basic(A, B, str));
4259 
4260   B->stencil.dim = A->stencil.dim;
4261   B->stencil.noc = A->stencil.noc;
4262   for (i = 0; i <= A->stencil.dim; i++) {
4263     B->stencil.dims[i]   = A->stencil.dims[i];
4264     B->stencil.starts[i] = A->stencil.starts[i];
4265   }
4266 
4267   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4268   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4269   PetscFunctionReturn(PETSC_SUCCESS);
4270 }
4271 
4272 /*@C
4273    MatConvert - Converts a matrix to another matrix, either of the same
4274    or different type.
4275 
4276    Collective
4277 
4278    Input Parameters:
4279 +  mat - the matrix
4280 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4281    same type as the original matrix.
4282 -  reuse - denotes if the destination matrix is to be created or reused.
4283    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
4284    `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).
4285 
4286    Output Parameter:
4287 .  M - pointer to place new matrix
4288 
4289    Level: intermediate
4290 
4291    Notes:
4292    `MatConvert()` first creates a new matrix and then copies the data from
4293    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4294    entries of one matrix to another already existing matrix context.
4295 
4296    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4297    the MPI communicator of the generated matrix is always the same as the communicator
4298    of the input matrix.
4299 
4300 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4301 @*/
4302 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4303 {
4304   PetscBool  sametype, issame, flg;
4305   PetscBool3 issymmetric, ishermitian;
4306   char       convname[256], mtype[256];
4307   Mat        B;
4308 
4309   PetscFunctionBegin;
4310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4311   PetscValidType(mat, 1);
4312   PetscValidPointer(M, 4);
4313   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4314   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4315   MatCheckPreallocated(mat, 1);
4316 
4317   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4318   if (flg) newtype = mtype;
4319 
4320   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4321   PetscCall(PetscStrcmp(newtype, "same", &issame));
4322   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4323   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");
4324 
4325   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4326     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4327     PetscFunctionReturn(PETSC_SUCCESS);
4328   }
4329 
4330   /* Cache Mat options because some converters use MatHeaderReplace  */
4331   issymmetric = mat->symmetric;
4332   ishermitian = mat->hermitian;
4333 
4334   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4335     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4336     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4337   } else {
4338     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4339     const char *prefix[3]                                 = {"seq", "mpi", ""};
4340     PetscInt    i;
4341     /*
4342        Order of precedence:
4343        0) See if newtype is a superclass of the current matrix.
4344        1) See if a specialized converter is known to the current matrix.
4345        2) See if a specialized converter is known to the desired matrix class.
4346        3) See if a good general converter is registered for the desired class
4347           (as of 6/27/03 only MATMPIADJ falls into this category).
4348        4) See if a good general converter is known for the current matrix.
4349        5) Use a really basic converter.
4350     */
4351 
4352     /* 0) See if newtype is a superclass of the current matrix.
4353           i.e mat is mpiaij and newtype is aij */
4354     for (i = 0; i < 2; i++) {
4355       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4357       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4358       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4359       if (flg) {
4360         if (reuse == MAT_INPLACE_MATRIX) {
4361           PetscCall(PetscInfo(mat, "Early return\n"));
4362           PetscFunctionReturn(PETSC_SUCCESS);
4363         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4364           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4365           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4368           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4369           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4370           PetscFunctionReturn(PETSC_SUCCESS);
4371         }
4372       }
4373     }
4374     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4375     for (i = 0; i < 3; i++) {
4376       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4381       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4382       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4383       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4384       if (conv) goto foundconv;
4385     }
4386 
4387     /* 2)  See if a specialized converter is known to the desired matrix class. */
4388     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4389     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4390     PetscCall(MatSetType(B, newtype));
4391     for (i = 0; i < 3; i++) {
4392       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4396       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4397       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4398       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4399       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4400       if (conv) {
4401         PetscCall(MatDestroy(&B));
4402         goto foundconv;
4403       }
4404     }
4405 
4406     /* 3) See if a good general converter is registered for the desired class */
4407     conv = B->ops->convertfrom;
4408     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4409     PetscCall(MatDestroy(&B));
4410     if (conv) goto foundconv;
4411 
4412     /* 4) See if a good general converter is known for the current matrix */
4413     if (mat->ops->convert) conv = mat->ops->convert;
4414     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4415     if (conv) goto foundconv;
4416 
4417     /* 5) Use a really basic converter. */
4418     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4419     conv = MatConvert_Basic;
4420 
4421   foundconv:
4422     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4423     PetscCall((*conv)(mat, newtype, reuse, M));
4424     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4425       /* the block sizes must be same if the mappings are copied over */
4426       (*M)->rmap->bs = mat->rmap->bs;
4427       (*M)->cmap->bs = mat->cmap->bs;
4428       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4429       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4430       (*M)->rmap->mapping = mat->rmap->mapping;
4431       (*M)->cmap->mapping = mat->cmap->mapping;
4432     }
4433     (*M)->stencil.dim = mat->stencil.dim;
4434     (*M)->stencil.noc = mat->stencil.noc;
4435     for (i = 0; i <= mat->stencil.dim; i++) {
4436       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4437       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4438     }
4439     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4440   }
4441   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4442 
4443   /* Copy Mat options */
4444   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4445   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4446   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4447   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4448   PetscFunctionReturn(PETSC_SUCCESS);
4449 }
4450 
4451 /*@C
4452    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4453 
4454    Not Collective
4455 
4456    Input Parameter:
4457 .  mat - the matrix, must be a factored matrix
4458 
4459    Output Parameter:
4460 .   type - the string name of the package (do not free this string)
4461 
4462    Level: intermediate
4463 
4464    Fortran Note:
4465    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4466 
4467 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4468 @*/
4469 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4470 {
4471   PetscErrorCode (*conv)(Mat, MatSolverType *);
4472 
4473   PetscFunctionBegin;
4474   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4475   PetscValidType(mat, 1);
4476   PetscValidPointer(type, 2);
4477   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4478   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4479   if (conv) PetscCall((*conv)(mat, type));
4480   else *type = MATSOLVERPETSC;
4481   PetscFunctionReturn(PETSC_SUCCESS);
4482 }
4483 
4484 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4485 struct _MatSolverTypeForSpecifcType {
4486   MatType mtype;
4487   /* no entry for MAT_FACTOR_NONE */
4488   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4489   MatSolverTypeForSpecifcType next;
4490 };
4491 
4492 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4493 struct _MatSolverTypeHolder {
4494   char                       *name;
4495   MatSolverTypeForSpecifcType handlers;
4496   MatSolverTypeHolder         next;
4497 };
4498 
4499 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4500 
4501 /*@C
4502    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4503 
4504    Input Parameters:
4505 +    package - name of the package, for example petsc or superlu
4506 .    mtype - the matrix type that works with this package
4507 .    ftype - the type of factorization supported by the package
4508 -    createfactor - routine that will create the factored matrix ready to be used
4509 
4510     Level: developer
4511 
4512 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4513 @*/
4514 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4515 {
4516   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4517   PetscBool                   flg;
4518   MatSolverTypeForSpecifcType inext, iprev = NULL;
4519 
4520   PetscFunctionBegin;
4521   PetscCall(MatInitializePackage());
4522   if (!next) {
4523     PetscCall(PetscNew(&MatSolverTypeHolders));
4524     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4525     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4526     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4527     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4528     PetscFunctionReturn(PETSC_SUCCESS);
4529   }
4530   while (next) {
4531     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4532     if (flg) {
4533       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4534       inext = next->handlers;
4535       while (inext) {
4536         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4537         if (flg) {
4538           inext->createfactor[(int)ftype - 1] = createfactor;
4539           PetscFunctionReturn(PETSC_SUCCESS);
4540         }
4541         iprev = inext;
4542         inext = inext->next;
4543       }
4544       PetscCall(PetscNew(&iprev->next));
4545       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4546       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4547       PetscFunctionReturn(PETSC_SUCCESS);
4548     }
4549     prev = next;
4550     next = next->next;
4551   }
4552   PetscCall(PetscNew(&prev->next));
4553   PetscCall(PetscStrallocpy(package, &prev->next->name));
4554   PetscCall(PetscNew(&prev->next->handlers));
4555   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4556   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4557   PetscFunctionReturn(PETSC_SUCCESS);
4558 }
4559 
4560 /*@C
4561    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4562 
4563    Input Parameters:
4564 +    type - name of the package, for example petsc or superlu
4565 .    ftype - the type of factorization supported by the type
4566 -    mtype - the matrix type that works with this type
4567 
4568    Output Parameters:
4569 +   foundtype - `PETSC_TRUE` if the type was registered
4570 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4571 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4572 
4573     Level: developer
4574 
4575 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4576 @*/
4577 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4578 {
4579   MatSolverTypeHolder         next = MatSolverTypeHolders;
4580   PetscBool                   flg;
4581   MatSolverTypeForSpecifcType inext;
4582 
4583   PetscFunctionBegin;
4584   if (foundtype) *foundtype = PETSC_FALSE;
4585   if (foundmtype) *foundmtype = PETSC_FALSE;
4586   if (createfactor) *createfactor = NULL;
4587 
4588   if (type) {
4589     while (next) {
4590       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4591       if (flg) {
4592         if (foundtype) *foundtype = PETSC_TRUE;
4593         inext = next->handlers;
4594         while (inext) {
4595           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4596           if (flg) {
4597             if (foundmtype) *foundmtype = PETSC_TRUE;
4598             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4599             PetscFunctionReturn(PETSC_SUCCESS);
4600           }
4601           inext = inext->next;
4602         }
4603       }
4604       next = next->next;
4605     }
4606   } else {
4607     while (next) {
4608       inext = next->handlers;
4609       while (inext) {
4610         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4611         if (flg && inext->createfactor[(int)ftype - 1]) {
4612           if (foundtype) *foundtype = PETSC_TRUE;
4613           if (foundmtype) *foundmtype = PETSC_TRUE;
4614           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4615           PetscFunctionReturn(PETSC_SUCCESS);
4616         }
4617         inext = inext->next;
4618       }
4619       next = next->next;
4620     }
4621     /* try with base classes inext->mtype */
4622     next = MatSolverTypeHolders;
4623     while (next) {
4624       inext = next->handlers;
4625       while (inext) {
4626         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4627         if (flg && inext->createfactor[(int)ftype - 1]) {
4628           if (foundtype) *foundtype = PETSC_TRUE;
4629           if (foundmtype) *foundmtype = PETSC_TRUE;
4630           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4631           PetscFunctionReturn(PETSC_SUCCESS);
4632         }
4633         inext = inext->next;
4634       }
4635       next = next->next;
4636     }
4637   }
4638   PetscFunctionReturn(PETSC_SUCCESS);
4639 }
4640 
4641 PetscErrorCode MatSolverTypeDestroy(void)
4642 {
4643   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4644   MatSolverTypeForSpecifcType inext, iprev;
4645 
4646   PetscFunctionBegin;
4647   while (next) {
4648     PetscCall(PetscFree(next->name));
4649     inext = next->handlers;
4650     while (inext) {
4651       PetscCall(PetscFree(inext->mtype));
4652       iprev = inext;
4653       inext = inext->next;
4654       PetscCall(PetscFree(iprev));
4655     }
4656     prev = next;
4657     next = next->next;
4658     PetscCall(PetscFree(prev));
4659   }
4660   MatSolverTypeHolders = NULL;
4661   PetscFunctionReturn(PETSC_SUCCESS);
4662 }
4663 
4664 /*@C
4665    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4666 
4667    Logically Collective
4668 
4669    Input Parameter:
4670 .  mat - the matrix
4671 
4672    Output Parameter:
4673 .  flg - `PETSC_TRUE` if uses the ordering
4674 
4675    Level: developer
4676 
4677    Note:
4678    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4679    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4680 
4681 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4682 @*/
4683 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4684 {
4685   PetscFunctionBegin;
4686   *flg = mat->canuseordering;
4687   PetscFunctionReturn(PETSC_SUCCESS);
4688 }
4689 
4690 /*@C
4691    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4692 
4693    Logically Collective
4694 
4695    Input Parameters:
4696 +  mat - the matrix obtained with `MatGetFactor()`
4697 -  ftype - the factorization type to be used
4698 
4699    Output Parameter:
4700 .  otype - the preferred ordering type
4701 
4702    Level: developer
4703 
4704 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4705 @*/
4706 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4707 {
4708   PetscFunctionBegin;
4709   *otype = mat->preferredordering[ftype];
4710   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4711   PetscFunctionReturn(PETSC_SUCCESS);
4712 }
4713 
4714 /*@C
4715    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4716 
4717    Collective
4718 
4719    Input Parameters:
4720 +  mat - the matrix
4721 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4722 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4723 
4724    Output Parameter:
4725 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4726 
4727    Options Database Key:
4728 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4729                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4730 
4731    Level: intermediate
4732 
4733    Notes:
4734      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4735      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4736 
4737      Users usually access the factorization solvers via `KSP`
4738 
4739       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4740      such as pastix, superlu, mumps etc.
4741 
4742       PETSc must have been ./configure to use the external solver, using the option --download-package
4743 
4744       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4745       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4746       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4747 
4748    Developer Note:
4749       This should actually be called `MatCreateFactor()` since it creates a new factor object
4750 
4751 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4752           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4753 @*/
4754 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4755 {
4756   PetscBool foundtype, foundmtype;
4757   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4758 
4759   PetscFunctionBegin;
4760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4761   PetscValidType(mat, 1);
4762 
4763   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4764   MatCheckPreallocated(mat, 1);
4765 
4766   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4767   if (!foundtype) {
4768     if (type) {
4769       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],
4770               ((PetscObject)mat)->type_name, type);
4771     } else {
4772       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);
4773     }
4774   }
4775   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4776   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);
4777 
4778   PetscCall((*conv)(mat, ftype, f));
4779   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4780   PetscFunctionReturn(PETSC_SUCCESS);
4781 }
4782 
4783 /*@C
4784    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4785 
4786    Not Collective
4787 
4788    Input Parameters:
4789 +  mat - the matrix
4790 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4791 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4792 
4793    Output Parameter:
4794 .    flg - PETSC_TRUE if the factorization is available
4795 
4796    Level: intermediate
4797 
4798    Notes:
4799       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4800      such as pastix, superlu, mumps etc.
4801 
4802       PETSc must have been ./configure to use the external solver, using the option --download-package
4803 
4804    Developer Note:
4805       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4806 
4807 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4808           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4809 @*/
4810 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4811 {
4812   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4813 
4814   PetscFunctionBegin;
4815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4816   PetscValidType(mat, 1);
4817   PetscValidBoolPointer(flg, 4);
4818 
4819   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4820   MatCheckPreallocated(mat, 1);
4821 
4822   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4823   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4824   PetscFunctionReturn(PETSC_SUCCESS);
4825 }
4826 
4827 /*@
4828    MatDuplicate - Duplicates a matrix including the non-zero structure.
4829 
4830    Collective
4831 
4832    Input Parameters:
4833 +  mat - the matrix
4834 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4835         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4836 
4837    Output Parameter:
4838 .  M - pointer to place new matrix
4839 
4840    Level: intermediate
4841 
4842    Notes:
4843     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4844 
4845     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.
4846 
4847     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
4848     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4849     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4850 
4851 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4852 @*/
4853 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4854 {
4855   Mat         B;
4856   VecType     vtype;
4857   PetscInt    i;
4858   PetscObject dm, container_h, container_d;
4859   void (*viewf)(void);
4860 
4861   PetscFunctionBegin;
4862   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4863   PetscValidType(mat, 1);
4864   PetscValidPointer(M, 3);
4865   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4866   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4867   MatCheckPreallocated(mat, 1);
4868 
4869   *M = NULL;
4870   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4871   PetscUseTypeMethod(mat, duplicate, op, M);
4872   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4873   B = *M;
4874 
4875   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4876   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4877   PetscCall(MatGetVecType(mat, &vtype));
4878   PetscCall(MatSetVecType(B, vtype));
4879 
4880   B->stencil.dim = mat->stencil.dim;
4881   B->stencil.noc = mat->stencil.noc;
4882   for (i = 0; i <= mat->stencil.dim; i++) {
4883     B->stencil.dims[i]   = mat->stencil.dims[i];
4884     B->stencil.starts[i] = mat->stencil.starts[i];
4885   }
4886 
4887   B->nooffproczerorows = mat->nooffproczerorows;
4888   B->nooffprocentries  = mat->nooffprocentries;
4889 
4890   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4891   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4892   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4893   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4894   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4895   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4896   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4897   PetscFunctionReturn(PETSC_SUCCESS);
4898 }
4899 
4900 /*@
4901    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4902 
4903    Logically Collective
4904 
4905    Input Parameter:
4906 .  mat - the matrix
4907 
4908    Output Parameter:
4909 .  v - the diagonal of the matrix
4910 
4911    Level: intermediate
4912 
4913    Note:
4914    If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4915    of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4916    is larger than `ndiag`, the values of the remaining entries are unspecified.
4917 
4918    Currently only correct in parallel for square matrices.
4919 
4920 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4921 @*/
4922 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4923 {
4924   PetscFunctionBegin;
4925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4926   PetscValidType(mat, 1);
4927   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4928   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4929   MatCheckPreallocated(mat, 1);
4930   if (PetscDefined(USE_DEBUG)) {
4931     PetscInt nv, row, col, ndiag;
4932 
4933     PetscCall(VecGetLocalSize(v, &nv));
4934     PetscCall(MatGetLocalSize(mat, &row, &col));
4935     ndiag = PetscMin(row, col);
4936     PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag);
4937   }
4938 
4939   PetscUseTypeMethod(mat, getdiagonal, v);
4940   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4941   PetscFunctionReturn(PETSC_SUCCESS);
4942 }
4943 
4944 /*@C
4945    MatGetRowMin - Gets the minimum value (of the real part) of each
4946         row of the matrix
4947 
4948    Logically Collective
4949 
4950    Input Parameter:
4951 .  mat - the matrix
4952 
4953    Output Parameters:
4954 +  v - the vector for storing the maximums
4955 -  idx - the indices of the column found for each row (optional)
4956 
4957    Level: intermediate
4958 
4959    Note:
4960     The result of this call are the same as if one converted the matrix to dense format
4961       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4962 
4963     This code is only implemented for a couple of matrix formats.
4964 
4965 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4966           `MatGetRowMax()`
4967 @*/
4968 PetscErrorCode MatGetRowMin(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 
4976   if (!mat->cmap->N) {
4977     PetscCall(VecSet(v, PETSC_MAX_REAL));
4978     if (idx) {
4979       PetscInt i, m = mat->rmap->n;
4980       for (i = 0; i < m; i++) idx[i] = -1;
4981     }
4982   } else {
4983     MatCheckPreallocated(mat, 1);
4984   }
4985   PetscUseTypeMethod(mat, getrowmin, v, idx);
4986   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4987   PetscFunctionReturn(PETSC_SUCCESS);
4988 }
4989 
4990 /*@C
4991    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4992         row of the matrix
4993 
4994    Logically Collective
4995 
4996    Input Parameter:
4997 .  mat - the matrix
4998 
4999    Output Parameters:
5000 +  v - the vector for storing the minimums
5001 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5002 
5003    Level: intermediate
5004 
5005    Notes:
5006     if a row is completely empty or has only 0.0 values then the idx[] value for that
5007     row is 0 (the first column).
5008 
5009     This code is only implemented for a couple of matrix formats.
5010 
5011 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5012 @*/
5013 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5014 {
5015   PetscFunctionBegin;
5016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5017   PetscValidType(mat, 1);
5018   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5019   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5020   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5021 
5022   if (!mat->cmap->N) {
5023     PetscCall(VecSet(v, 0.0));
5024     if (idx) {
5025       PetscInt i, m = mat->rmap->n;
5026       for (i = 0; i < m; i++) idx[i] = -1;
5027     }
5028   } else {
5029     MatCheckPreallocated(mat, 1);
5030     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5031     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5032   }
5033   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5034   PetscFunctionReturn(PETSC_SUCCESS);
5035 }
5036 
5037 /*@C
5038    MatGetRowMax - Gets the maximum value (of the real part) 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 (optional)
5049 
5050    Level: intermediate
5051 
5052    Notes:
5053     The result of this call are the same as if one converted the matrix to dense format
5054       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5055 
5056     This code is only implemented for a couple of matrix formats.
5057 
5058 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5059 @*/
5060 PetscErrorCode MatGetRowMax(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, PETSC_MIN_REAL));
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     PetscUseTypeMethod(mat, getrowmax, v, idx);
5077   }
5078   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5079   PetscFunctionReturn(PETSC_SUCCESS);
5080 }
5081 
5082 /*@C
5083    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5084         row of the matrix
5085 
5086    Logically Collective
5087 
5088    Input Parameter:
5089 .  mat - the matrix
5090 
5091    Output Parameters:
5092 +  v - the vector for storing the maximums
5093 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5094 
5095    Level: intermediate
5096 
5097    Notes:
5098     if a row is completely empty or has only 0.0 values then the idx[] value for that
5099     row is 0 (the first column).
5100 
5101     This code is only implemented for a couple of matrix formats.
5102 
5103 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5104 @*/
5105 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5106 {
5107   PetscFunctionBegin;
5108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5109   PetscValidType(mat, 1);
5110   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5112 
5113   if (!mat->cmap->N) {
5114     PetscCall(VecSet(v, 0.0));
5115     if (idx) {
5116       PetscInt i, m = mat->rmap->n;
5117       for (i = 0; i < m; i++) idx[i] = -1;
5118     }
5119   } else {
5120     MatCheckPreallocated(mat, 1);
5121     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5122     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5123   }
5124   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5125   PetscFunctionReturn(PETSC_SUCCESS);
5126 }
5127 
5128 /*@
5129    MatGetRowSum - Gets the sum of each row of the matrix
5130 
5131    Logically or Neighborhood Collective
5132 
5133    Input Parameter:
5134 .  mat - the matrix
5135 
5136    Output Parameter:
5137 .  v - the vector for storing the sum of rows
5138 
5139    Level: intermediate
5140 
5141    Notes:
5142     This code is slow since it is not currently specialized for different formats
5143 
5144 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5145 @*/
5146 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5147 {
5148   Vec ones;
5149 
5150   PetscFunctionBegin;
5151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5152   PetscValidType(mat, 1);
5153   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5154   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5155   MatCheckPreallocated(mat, 1);
5156   PetscCall(MatCreateVecs(mat, &ones, NULL));
5157   PetscCall(VecSet(ones, 1.));
5158   PetscCall(MatMult(mat, ones, v));
5159   PetscCall(VecDestroy(&ones));
5160   PetscFunctionReturn(PETSC_SUCCESS);
5161 }
5162 
5163 /*@
5164    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5165    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5166 
5167    Collective
5168 
5169    Input Parameter:
5170 .  mat - the matrix to provide the transpose
5171 
5172    Output Parameter:
5173 .  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
5174 
5175    Level: advanced
5176 
5177    Note:
5178    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
5179    routine allows bypassing that call.
5180 
5181 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5182 @*/
5183 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5184 {
5185   PetscContainer  rB = NULL;
5186   MatParentState *rb = NULL;
5187 
5188   PetscFunctionBegin;
5189   PetscCall(PetscNew(&rb));
5190   rb->id    = ((PetscObject)mat)->id;
5191   rb->state = 0;
5192   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5193   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5194   PetscCall(PetscContainerSetPointer(rB, rb));
5195   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5196   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5197   PetscCall(PetscObjectDereference((PetscObject)rB));
5198   PetscFunctionReturn(PETSC_SUCCESS);
5199 }
5200 
5201 /*@
5202    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5203 
5204    Collective
5205 
5206    Input Parameters:
5207 +  mat - the matrix to transpose
5208 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5209 
5210    Output Parameter:
5211 .  B - the transpose
5212 
5213    Level: intermediate
5214 
5215    Notes:
5216      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5217 
5218      `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
5219      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5220 
5221      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.
5222 
5223      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5224 
5225      If mat is unchanged from the last call this function returns immediately without recomputing the result
5226 
5227      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5228 
5229 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5230           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5231 @*/
5232 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5233 {
5234   PetscContainer  rB = NULL;
5235   MatParentState *rb = NULL;
5236 
5237   PetscFunctionBegin;
5238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5239   PetscValidType(mat, 1);
5240   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5241   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5242   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5243   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5244   MatCheckPreallocated(mat, 1);
5245   if (reuse == MAT_REUSE_MATRIX) {
5246     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5247     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5248     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5249     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5250     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5251   }
5252 
5253   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5254   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5255     PetscUseTypeMethod(mat, transpose, reuse, B);
5256     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5257   }
5258   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5259 
5260   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5261   if (reuse != MAT_INPLACE_MATRIX) {
5262     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5263     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5264     rb->state        = ((PetscObject)mat)->state;
5265     rb->nonzerostate = mat->nonzerostate;
5266   }
5267   PetscFunctionReturn(PETSC_SUCCESS);
5268 }
5269 
5270 /*@
5271    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5272 
5273    Collective
5274 
5275    Input Parameter:
5276 .  A - the matrix to transpose
5277 
5278    Output Parameter:
5279 .  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
5280       numerical portion.
5281 
5282    Level: intermediate
5283 
5284    Note:
5285    This is not supported for many matrix types, use `MatTranspose()` in those cases
5286 
5287 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5288 @*/
5289 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5290 {
5291   PetscFunctionBegin;
5292   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5293   PetscValidType(A, 1);
5294   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5295   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5296   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5297   PetscUseTypeMethod(A, transposesymbolic, B);
5298   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5299 
5300   PetscCall(MatTransposeSetPrecursor(A, *B));
5301   PetscFunctionReturn(PETSC_SUCCESS);
5302 }
5303 
5304 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5305 {
5306   PetscContainer  rB;
5307   MatParentState *rb;
5308 
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5311   PetscValidType(A, 1);
5312   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5313   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5314   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5315   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5316   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5317   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5318   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5319   PetscFunctionReturn(PETSC_SUCCESS);
5320 }
5321 
5322 /*@
5323    MatIsTranspose - Test whether a matrix is another one's transpose,
5324         or its own, in which case it tests symmetry.
5325 
5326    Collective
5327 
5328    Input Parameters:
5329 +  A - the matrix to test
5330 .  B - the matrix to test against, this can equal the first parameter
5331 -  tol - tolerance, differences between entries smaller than this are counted as zero
5332 
5333    Output Parameter:
5334 .  flg - the result
5335 
5336    Level: intermediate
5337 
5338    Notes:
5339    Only available for `MATAIJ` matrices.
5340 
5341    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5342    test involves parallel copies of the block-offdiagonal parts of the matrix.
5343 
5344 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5345 @*/
5346 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5347 {
5348   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5349 
5350   PetscFunctionBegin;
5351   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5352   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5353   PetscValidBoolPointer(flg, 4);
5354   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5355   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5356   *flg = PETSC_FALSE;
5357   if (f && g) {
5358     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5359     PetscCall((*f)(A, B, tol, flg));
5360   } else {
5361     MatType mattype;
5362 
5363     PetscCall(MatGetType(f ? B : A, &mattype));
5364     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5365   }
5366   PetscFunctionReturn(PETSC_SUCCESS);
5367 }
5368 
5369 /*@
5370    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5371 
5372    Collective
5373 
5374    Input Parameters:
5375 +  mat - the matrix to transpose and complex conjugate
5376 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5377 
5378    Output Parameter:
5379 .  B - the Hermitian transpose
5380 
5381    Level: intermediate
5382 
5383 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5384 @*/
5385 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5386 {
5387   PetscFunctionBegin;
5388   PetscCall(MatTranspose(mat, reuse, B));
5389 #if defined(PETSC_USE_COMPLEX)
5390   PetscCall(MatConjugate(*B));
5391 #endif
5392   PetscFunctionReturn(PETSC_SUCCESS);
5393 }
5394 
5395 /*@
5396    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5397 
5398    Collective
5399 
5400    Input Parameters:
5401 +  A - the matrix to test
5402 .  B - the matrix to test against, this can equal the first parameter
5403 -  tol - tolerance, differences between entries smaller than this are counted as zero
5404 
5405    Output Parameter:
5406 .  flg - the result
5407 
5408    Level: intermediate
5409 
5410    Notes:
5411    Only available for `MATAIJ` matrices.
5412 
5413    The sequential algorithm
5414    has a running time of the order of the number of nonzeros; the parallel
5415    test involves parallel copies of the block-offdiagonal parts of the matrix.
5416 
5417 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5418 @*/
5419 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5420 {
5421   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5422 
5423   PetscFunctionBegin;
5424   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5425   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5426   PetscValidBoolPointer(flg, 4);
5427   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5428   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5429   if (f && g) {
5430     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5431     PetscCall((*f)(A, B, tol, flg));
5432   }
5433   PetscFunctionReturn(PETSC_SUCCESS);
5434 }
5435 
5436 /*@
5437    MatPermute - Creates a new matrix with rows and columns permuted from the
5438    original.
5439 
5440    Collective
5441 
5442    Input Parameters:
5443 +  mat - the matrix to permute
5444 .  row - row permutation, each processor supplies only the permutation for its rows
5445 -  col - column permutation, each processor supplies only the permutation for its columns
5446 
5447    Output Parameter:
5448 .  B - the permuted matrix
5449 
5450    Level: advanced
5451 
5452    Note:
5453    The index sets map from row/col of permuted matrix to row/col of original matrix.
5454    The index sets should be on the same communicator as mat and have the same local sizes.
5455 
5456    Developer Note:
5457      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5458      exploit the fact that row and col are permutations, consider implementing the
5459      more general `MatCreateSubMatrix()` instead.
5460 
5461 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5462 @*/
5463 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5464 {
5465   PetscFunctionBegin;
5466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5467   PetscValidType(mat, 1);
5468   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5469   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5470   PetscValidPointer(B, 4);
5471   PetscCheckSameComm(mat, 1, row, 2);
5472   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5473   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5474   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5475   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5476   MatCheckPreallocated(mat, 1);
5477 
5478   if (mat->ops->permute) {
5479     PetscUseTypeMethod(mat, permute, row, col, B);
5480     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5481   } else {
5482     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5483   }
5484   PetscFunctionReturn(PETSC_SUCCESS);
5485 }
5486 
5487 /*@
5488    MatEqual - Compares two matrices.
5489 
5490    Collective
5491 
5492    Input Parameters:
5493 +  A - the first matrix
5494 -  B - the second matrix
5495 
5496    Output Parameter:
5497 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5498 
5499    Level: intermediate
5500 
5501 .seealso: [](ch_matrices), `Mat`
5502 @*/
5503 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5504 {
5505   PetscFunctionBegin;
5506   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5507   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5508   PetscValidType(A, 1);
5509   PetscValidType(B, 2);
5510   PetscValidBoolPointer(flg, 3);
5511   PetscCheckSameComm(A, 1, B, 2);
5512   MatCheckPreallocated(A, 1);
5513   MatCheckPreallocated(B, 2);
5514   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5515   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5516   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,
5517              B->cmap->N);
5518   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5519     PetscUseTypeMethod(A, equal, B, flg);
5520   } else {
5521     PetscCall(MatMultEqual(A, B, 10, flg));
5522   }
5523   PetscFunctionReturn(PETSC_SUCCESS);
5524 }
5525 
5526 /*@
5527    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5528    matrices that are stored as vectors.  Either of the two scaling
5529    matrices can be `NULL`.
5530 
5531    Collective
5532 
5533    Input Parameters:
5534 +  mat - the matrix to be scaled
5535 .  l - the left scaling vector (or `NULL`)
5536 -  r - the right scaling vector (or `NULL`)
5537 
5538    Level: intermediate
5539 
5540    Note:
5541    `MatDiagonalScale()` computes A = LAR, where
5542    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5543    The L scales the rows of the matrix, the R scales the columns of the matrix.
5544 
5545 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5546 @*/
5547 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5548 {
5549   PetscFunctionBegin;
5550   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5551   PetscValidType(mat, 1);
5552   if (l) {
5553     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5554     PetscCheckSameComm(mat, 1, l, 2);
5555   }
5556   if (r) {
5557     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5558     PetscCheckSameComm(mat, 1, r, 3);
5559   }
5560   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5561   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5562   MatCheckPreallocated(mat, 1);
5563   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5564 
5565   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5566   PetscUseTypeMethod(mat, diagonalscale, l, r);
5567   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5568   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5569   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5570   PetscFunctionReturn(PETSC_SUCCESS);
5571 }
5572 
5573 /*@
5574     MatScale - Scales all elements of a matrix by a given number.
5575 
5576     Logically Collective
5577 
5578     Input Parameters:
5579 +   mat - the matrix to be scaled
5580 -   a  - the scaling value
5581 
5582     Level: intermediate
5583 
5584 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5585 @*/
5586 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5587 {
5588   PetscFunctionBegin;
5589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5590   PetscValidType(mat, 1);
5591   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5592   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5593   PetscValidLogicalCollectiveScalar(mat, a, 2);
5594   MatCheckPreallocated(mat, 1);
5595 
5596   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5597   if (a != (PetscScalar)1.0) {
5598     PetscUseTypeMethod(mat, scale, a);
5599     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5600   }
5601   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5602   PetscFunctionReturn(PETSC_SUCCESS);
5603 }
5604 
5605 /*@
5606    MatNorm - Calculates various norms of a matrix.
5607 
5608    Collective
5609 
5610    Input Parameters:
5611 +  mat - the matrix
5612 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5613 
5614    Output Parameter:
5615 .  nrm - the resulting norm
5616 
5617    Level: intermediate
5618 
5619 .seealso: [](ch_matrices), `Mat`
5620 @*/
5621 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5622 {
5623   PetscFunctionBegin;
5624   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5625   PetscValidType(mat, 1);
5626   PetscValidRealPointer(nrm, 3);
5627 
5628   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5629   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5630   MatCheckPreallocated(mat, 1);
5631 
5632   PetscUseTypeMethod(mat, norm, type, nrm);
5633   PetscFunctionReturn(PETSC_SUCCESS);
5634 }
5635 
5636 /*
5637      This variable is used to prevent counting of MatAssemblyBegin() that
5638    are called from within a MatAssemblyEnd().
5639 */
5640 static PetscInt MatAssemblyEnd_InUse = 0;
5641 /*@
5642    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5643    be called after completing all calls to `MatSetValues()`.
5644 
5645    Collective
5646 
5647    Input Parameters:
5648 +  mat - the matrix
5649 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5650 
5651    Level: beginner
5652 
5653    Notes:
5654    `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5655    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5656 
5657    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5658    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5659    using the matrix.
5660 
5661    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5662    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
5663    a global collective operation requiring all processes that share the matrix.
5664 
5665    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5666    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5667    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5668 
5669 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5670 @*/
5671 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5672 {
5673   PetscFunctionBegin;
5674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5675   PetscValidType(mat, 1);
5676   MatCheckPreallocated(mat, 1);
5677   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5678   if (mat->assembled) {
5679     mat->was_assembled = PETSC_TRUE;
5680     mat->assembled     = PETSC_FALSE;
5681   }
5682 
5683   if (!MatAssemblyEnd_InUse) {
5684     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5685     PetscTryTypeMethod(mat, assemblybegin, type);
5686     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5687   } else PetscTryTypeMethod(mat, assemblybegin, type);
5688   PetscFunctionReturn(PETSC_SUCCESS);
5689 }
5690 
5691 /*@
5692    MatAssembled - Indicates if a matrix has been assembled and is ready for
5693      use; for example, in matrix-vector product.
5694 
5695    Not Collective
5696 
5697    Input Parameter:
5698 .  mat - the matrix
5699 
5700    Output Parameter:
5701 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5702 
5703    Level: advanced
5704 
5705 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5706 @*/
5707 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5708 {
5709   PetscFunctionBegin;
5710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5711   PetscValidBoolPointer(assembled, 2);
5712   *assembled = mat->assembled;
5713   PetscFunctionReturn(PETSC_SUCCESS);
5714 }
5715 
5716 /*@
5717    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5718    be called after `MatAssemblyBegin()`.
5719 
5720    Collective
5721 
5722    Input Parameters:
5723 +  mat - the matrix
5724 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5725 
5726    Options Database Keys:
5727 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5728 .  -mat_view ::ascii_info_detail - Prints more detailed info
5729 .  -mat_view - Prints matrix in ASCII format
5730 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5731 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5732 .  -display <name> - Sets display name (default is host)
5733 .  -draw_pause <sec> - Sets number of seconds to pause after display
5734 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5735 .  -viewer_socket_machine <machine> - Machine to use for socket
5736 .  -viewer_socket_port <port> - Port number to use for socket
5737 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5738 
5739    Level: beginner
5740 
5741 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5742 @*/
5743 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5744 {
5745   static PetscInt inassm = 0;
5746   PetscBool       flg    = PETSC_FALSE;
5747 
5748   PetscFunctionBegin;
5749   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5750   PetscValidType(mat, 1);
5751 
5752   inassm++;
5753   MatAssemblyEnd_InUse++;
5754   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5755     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5756     PetscTryTypeMethod(mat, assemblyend, type);
5757     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5758   } else PetscTryTypeMethod(mat, assemblyend, type);
5759 
5760   /* Flush assembly is not a true assembly */
5761   if (type != MAT_FLUSH_ASSEMBLY) {
5762     if (mat->num_ass) {
5763       if (!mat->symmetry_eternal) {
5764         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5765         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5766       }
5767       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5768       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5769     }
5770     mat->num_ass++;
5771     mat->assembled        = PETSC_TRUE;
5772     mat->ass_nonzerostate = mat->nonzerostate;
5773   }
5774 
5775   mat->insertmode = NOT_SET_VALUES;
5776   MatAssemblyEnd_InUse--;
5777   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5778   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5779     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5780 
5781     if (mat->checksymmetryonassembly) {
5782       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5783       if (flg) {
5784         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5785       } else {
5786         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5787       }
5788     }
5789     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5790   }
5791   inassm--;
5792   PetscFunctionReturn(PETSC_SUCCESS);
5793 }
5794 
5795 /*@
5796    MatSetOption - Sets a parameter option for a matrix. Some options
5797    may be specific to certain storage formats.  Some options
5798    determine how values will be inserted (or added). Sorted,
5799    row-oriented input will generally assemble the fastest. The default
5800    is row-oriented.
5801 
5802    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5803 
5804    Input Parameters:
5805 +  mat - the matrix
5806 .  option - the option, one of those listed below (and possibly others),
5807 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5808 
5809   Options Describing Matrix Structure:
5810 +    `MAT_SPD` - symmetric positive definite
5811 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5812 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5813 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5814 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5815 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5816 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5817 
5818    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5819    do not need to be computed (usually at a high cost)
5820 
5821    Options For Use with `MatSetValues()`:
5822    Insert a logically dense subblock, which can be
5823 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5824 
5825    These options reflect the data you pass in with `MatSetValues()`; it has
5826    nothing to do with how the data is stored internally in the matrix
5827    data structure.
5828 
5829    When (re)assembling a matrix, we can restrict the input for
5830    efficiency/debugging purposes.  These options include
5831 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5832 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5833 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5834 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5835 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5836 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5837         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5838         performance for very large process counts.
5839 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5840         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5841         functions, instead sending only neighbor messages.
5842 
5843    Level: intermediate
5844 
5845    Notes:
5846    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5847 
5848    Some options are relevant only for particular matrix types and
5849    are thus ignored by others.  Other options are not supported by
5850    certain matrix types and will generate an error message if set.
5851 
5852    If using Fortran to compute a matrix, one may need to
5853    use the column-oriented option (or convert to the row-oriented
5854    format).
5855 
5856    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5857    that would generate a new entry in the nonzero structure is instead
5858    ignored.  Thus, if memory has not already been allocated for this particular
5859    data, then the insertion is ignored. For dense matrices, in which
5860    the entire array is allocated, no entries are ever ignored.
5861    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5862 
5863    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5864    that would generate a new entry in the nonzero structure instead produces
5865    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
5866 
5867    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5868    that would generate a new entry that has not been preallocated will
5869    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5870    only.) This is a useful flag when debugging matrix memory preallocation.
5871    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5872 
5873    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5874    other processors should be dropped, rather than stashed.
5875    This is useful if you know that the "owning" processor is also
5876    always generating the correct matrix entries, so that PETSc need
5877    not transfer duplicate entries generated on another processor.
5878 
5879    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5880    searches during matrix assembly. When this flag is set, the hash table
5881    is created during the first matrix assembly. This hash table is
5882    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5883    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5884    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5885    supported by `MATMPIBAIJ` format only.
5886 
5887    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5888    are kept in the nonzero structure
5889 
5890    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5891    a zero location in the matrix
5892 
5893    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5894 
5895    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5896         zero row routines and thus improves performance for very large process counts.
5897 
5898    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5899         part of the matrix (since they should match the upper triangular part).
5900 
5901    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5902                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5903                      with finite difference schemes with non-periodic boundary conditions.
5904 
5905    Developer Note:
5906    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5907    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5908    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5909    not changed.
5910 
5911 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5912 @*/
5913 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5914 {
5915   PetscFunctionBegin;
5916   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5917   if (op > 0) {
5918     PetscValidLogicalCollectiveEnum(mat, op, 2);
5919     PetscValidLogicalCollectiveBool(mat, flg, 3);
5920   }
5921 
5922   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);
5923 
5924   switch (op) {
5925   case MAT_FORCE_DIAGONAL_ENTRIES:
5926     mat->force_diagonals = flg;
5927     PetscFunctionReturn(PETSC_SUCCESS);
5928   case MAT_NO_OFF_PROC_ENTRIES:
5929     mat->nooffprocentries = flg;
5930     PetscFunctionReturn(PETSC_SUCCESS);
5931   case MAT_SUBSET_OFF_PROC_ENTRIES:
5932     mat->assembly_subset = flg;
5933     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5934 #if !defined(PETSC_HAVE_MPIUNI)
5935       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5936 #endif
5937       mat->stash.first_assembly_done = PETSC_FALSE;
5938     }
5939     PetscFunctionReturn(PETSC_SUCCESS);
5940   case MAT_NO_OFF_PROC_ZERO_ROWS:
5941     mat->nooffproczerorows = flg;
5942     PetscFunctionReturn(PETSC_SUCCESS);
5943   case MAT_SPD:
5944     if (flg) {
5945       mat->spd                    = PETSC_BOOL3_TRUE;
5946       mat->symmetric              = PETSC_BOOL3_TRUE;
5947       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5948     } else {
5949       mat->spd = PETSC_BOOL3_FALSE;
5950     }
5951     break;
5952   case MAT_SYMMETRIC:
5953     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5954     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5955 #if !defined(PETSC_USE_COMPLEX)
5956     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5957 #endif
5958     break;
5959   case MAT_HERMITIAN:
5960     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5961     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5962 #if !defined(PETSC_USE_COMPLEX)
5963     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5964 #endif
5965     break;
5966   case MAT_STRUCTURALLY_SYMMETRIC:
5967     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5968     break;
5969   case MAT_SYMMETRY_ETERNAL:
5970     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");
5971     mat->symmetry_eternal = flg;
5972     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5973     break;
5974   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5975     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");
5976     mat->structural_symmetry_eternal = flg;
5977     break;
5978   case MAT_SPD_ETERNAL:
5979     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");
5980     mat->spd_eternal = flg;
5981     if (flg) {
5982       mat->structural_symmetry_eternal = PETSC_TRUE;
5983       mat->symmetry_eternal            = PETSC_TRUE;
5984     }
5985     break;
5986   case MAT_STRUCTURE_ONLY:
5987     mat->structure_only = flg;
5988     break;
5989   case MAT_SORTED_FULL:
5990     mat->sortedfull = flg;
5991     break;
5992   default:
5993     break;
5994   }
5995   PetscTryTypeMethod(mat, setoption, op, flg);
5996   PetscFunctionReturn(PETSC_SUCCESS);
5997 }
5998 
5999 /*@
6000    MatGetOption - Gets a parameter option that has been set for a matrix.
6001 
6002    Logically Collective
6003 
6004    Input Parameters:
6005 +  mat - the matrix
6006 -  option - the option, this only responds to certain options, check the code for which ones
6007 
6008    Output Parameter:
6009 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6010 
6011    Level: intermediate
6012 
6013     Notes:
6014     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6015 
6016     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6017     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6018 
6019 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6020     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6021 @*/
6022 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6023 {
6024   PetscFunctionBegin;
6025   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6026   PetscValidType(mat, 1);
6027 
6028   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);
6029   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()");
6030 
6031   switch (op) {
6032   case MAT_NO_OFF_PROC_ENTRIES:
6033     *flg = mat->nooffprocentries;
6034     break;
6035   case MAT_NO_OFF_PROC_ZERO_ROWS:
6036     *flg = mat->nooffproczerorows;
6037     break;
6038   case MAT_SYMMETRIC:
6039     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6040     break;
6041   case MAT_HERMITIAN:
6042     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6043     break;
6044   case MAT_STRUCTURALLY_SYMMETRIC:
6045     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6046     break;
6047   case MAT_SPD:
6048     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6049     break;
6050   case MAT_SYMMETRY_ETERNAL:
6051     *flg = mat->symmetry_eternal;
6052     break;
6053   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6054     *flg = mat->symmetry_eternal;
6055     break;
6056   default:
6057     break;
6058   }
6059   PetscFunctionReturn(PETSC_SUCCESS);
6060 }
6061 
6062 /*@
6063    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6064    this routine retains the old nonzero structure.
6065 
6066    Logically Collective
6067 
6068    Input Parameter:
6069 .  mat - the matrix
6070 
6071    Level: intermediate
6072 
6073    Note:
6074     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.
6075    See the Performance chapter of the users manual for information on preallocating matrices.
6076 
6077 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6078 @*/
6079 PetscErrorCode MatZeroEntries(Mat mat)
6080 {
6081   PetscFunctionBegin;
6082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6083   PetscValidType(mat, 1);
6084   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6085   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");
6086   MatCheckPreallocated(mat, 1);
6087 
6088   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6089   PetscUseTypeMethod(mat, zeroentries);
6090   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6091   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6092   PetscFunctionReturn(PETSC_SUCCESS);
6093 }
6094 
6095 /*@
6096    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6097    of a set of rows and columns of a matrix.
6098 
6099    Collective
6100 
6101    Input Parameters:
6102 +  mat - the matrix
6103 .  numRows - the number of rows/columns to zero
6104 .  rows - the global row indices
6105 .  diag - value put in the diagonal of the eliminated rows
6106 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6107 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6108 
6109    Level: intermediate
6110 
6111    Notes:
6112    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6113 
6114    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6115    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
6116 
6117    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6118    Krylov method to take advantage of the known solution on the zeroed rows.
6119 
6120    For the parallel case, all processes that share the matrix (i.e.,
6121    those in the communicator used for matrix creation) MUST call this
6122    routine, regardless of whether any rows being zeroed are owned by
6123    them.
6124 
6125    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6126 
6127    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6128    list only rows local to itself).
6129 
6130    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6131 
6132 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6133           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6134 @*/
6135 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6136 {
6137   PetscFunctionBegin;
6138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6139   PetscValidType(mat, 1);
6140   if (numRows) PetscValidIntPointer(rows, 3);
6141   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6142   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6143   MatCheckPreallocated(mat, 1);
6144 
6145   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6146   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6147   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6148   PetscFunctionReturn(PETSC_SUCCESS);
6149 }
6150 
6151 /*@
6152    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6153    of a set of rows and columns of a matrix.
6154 
6155    Collective
6156 
6157    Input Parameters:
6158 +  mat - the matrix
6159 .  is - the rows to zero
6160 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6161 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6162 -  b - optional vector of right hand side, that will be adjusted by provided solution
6163 
6164    Level: intermediate
6165 
6166    Note:
6167    See `MatZeroRowsColumns()` for details on how this routine operates.
6168 
6169 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6170           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6171 @*/
6172 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6173 {
6174   PetscInt        numRows;
6175   const PetscInt *rows;
6176 
6177   PetscFunctionBegin;
6178   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6179   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6180   PetscValidType(mat, 1);
6181   PetscValidType(is, 2);
6182   PetscCall(ISGetLocalSize(is, &numRows));
6183   PetscCall(ISGetIndices(is, &rows));
6184   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6185   PetscCall(ISRestoreIndices(is, &rows));
6186   PetscFunctionReturn(PETSC_SUCCESS);
6187 }
6188 
6189 /*@
6190    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6191    of a set of rows of a matrix.
6192 
6193    Collective
6194 
6195    Input Parameters:
6196 +  mat - the matrix
6197 .  numRows - the number of rows to zero
6198 .  rows - the global row indices
6199 .  diag - value put in the diagonal of the zeroed rows
6200 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6201 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6202 
6203    Level: intermediate
6204 
6205    Notes:
6206    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6207 
6208    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6209 
6210    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6211    Krylov method to take advantage of the known solution on the zeroed rows.
6212 
6213    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)
6214    from the matrix.
6215 
6216    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6217    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
6218    formats this does not alter the nonzero structure.
6219 
6220    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6221    of the matrix is not changed the values are
6222    merely zeroed.
6223 
6224    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6225    formats can optionally remove the main diagonal entry from the
6226    nonzero structure as well, by passing 0.0 as the final argument).
6227 
6228    For the parallel case, all processes that share the matrix (i.e.,
6229    those in the communicator used for matrix creation) MUST call this
6230    routine, regardless of whether any rows being zeroed are owned by
6231    them.
6232 
6233    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6234    list only rows local to itself).
6235 
6236    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6237    owns that are to be zeroed. This saves a global synchronization in the implementation.
6238 
6239 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6240           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6241 @*/
6242 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6243 {
6244   PetscFunctionBegin;
6245   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6246   PetscValidType(mat, 1);
6247   if (numRows) PetscValidIntPointer(rows, 3);
6248   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6249   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6250   MatCheckPreallocated(mat, 1);
6251 
6252   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6253   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6254   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6255   PetscFunctionReturn(PETSC_SUCCESS);
6256 }
6257 
6258 /*@
6259    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6260    of a set of rows of a matrix.
6261 
6262    Collective
6263 
6264    Input Parameters:
6265 +  mat - the matrix
6266 .  is - index set of rows to remove (if `NULL` then no row is removed)
6267 .  diag - value put in all diagonals of eliminated rows
6268 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6269 -  b - optional vector of right hand side, that will be adjusted by provided solution
6270 
6271    Level: intermediate
6272 
6273    Note:
6274    See `MatZeroRows()` for details on how this routine operates.
6275 
6276 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6277           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6278 @*/
6279 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6280 {
6281   PetscInt        numRows = 0;
6282   const PetscInt *rows    = NULL;
6283 
6284   PetscFunctionBegin;
6285   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6286   PetscValidType(mat, 1);
6287   if (is) {
6288     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6289     PetscCall(ISGetLocalSize(is, &numRows));
6290     PetscCall(ISGetIndices(is, &rows));
6291   }
6292   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6293   if (is) PetscCall(ISRestoreIndices(is, &rows));
6294   PetscFunctionReturn(PETSC_SUCCESS);
6295 }
6296 
6297 /*@
6298    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6299    of a set of rows of a matrix. These rows must be local to the process.
6300 
6301    Collective
6302 
6303    Input Parameters:
6304 +  mat - the matrix
6305 .  numRows - the number of rows to remove
6306 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6307 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6308 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6309 -  b - optional vector of right hand side, that will be adjusted by provided solution
6310 
6311    Level: intermediate
6312 
6313    Notes:
6314    See `MatZeroRows()` for details on how this routine operates.
6315 
6316    The grid coordinates are across the entire grid, not just the local portion
6317 
6318    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6319    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6320    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6321    `DM_BOUNDARY_PERIODIC` boundary type.
6322 
6323    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
6324    a single value per point) you can skip filling those indices.
6325 
6326    Fortran Note:
6327    `idxm` and `idxn` should be declared as
6328 $     MatStencil idxm(4, m)
6329    and the values inserted using
6330 .vb
6331     idxm(MatStencil_i, 1) = i
6332     idxm(MatStencil_j, 1) = j
6333     idxm(MatStencil_k, 1) = k
6334     idxm(MatStencil_c, 1) = c
6335    etc
6336 .ve
6337 
6338 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6339           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6340 @*/
6341 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6342 {
6343   PetscInt  dim    = mat->stencil.dim;
6344   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6345   PetscInt *dims   = mat->stencil.dims + 1;
6346   PetscInt *starts = mat->stencil.starts;
6347   PetscInt *dxm    = (PetscInt *)rows;
6348   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6349 
6350   PetscFunctionBegin;
6351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6352   PetscValidType(mat, 1);
6353   if (numRows) PetscValidPointer(rows, 3);
6354 
6355   PetscCall(PetscMalloc1(numRows, &jdxm));
6356   for (i = 0; i < numRows; ++i) {
6357     /* Skip unused dimensions (they are ordered k, j, i, c) */
6358     for (j = 0; j < 3 - sdim; ++j) dxm++;
6359     /* Local index in X dir */
6360     tmp = *dxm++ - starts[0];
6361     /* Loop over remaining dimensions */
6362     for (j = 0; j < dim - 1; ++j) {
6363       /* If nonlocal, set index to be negative */
6364       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6365       /* Update local index */
6366       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6367     }
6368     /* Skip component slot if necessary */
6369     if (mat->stencil.noc) dxm++;
6370     /* Local row number */
6371     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6372   }
6373   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6374   PetscCall(PetscFree(jdxm));
6375   PetscFunctionReturn(PETSC_SUCCESS);
6376 }
6377 
6378 /*@
6379    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6380    of a set of rows and columns of a matrix.
6381 
6382    Collective
6383 
6384    Input Parameters:
6385 +  mat - the matrix
6386 .  numRows - the number of rows/columns to remove
6387 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6388 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6389 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6390 -  b - optional vector of right hand side, that will be adjusted by provided solution
6391 
6392    Level: intermediate
6393 
6394    Notes:
6395    See `MatZeroRowsColumns()` for details on how this routine operates.
6396 
6397    The grid coordinates are across the entire grid, not just the local portion
6398 
6399    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6400    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6401    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6402    `DM_BOUNDARY_PERIODIC` boundary type.
6403 
6404    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
6405    a single value per point) you can skip filling those indices.
6406 
6407    Fortran Note:
6408    `idxm` and `idxn` should be declared as
6409 $     MatStencil idxm(4, m)
6410    and the values inserted using
6411 .vb
6412     idxm(MatStencil_i, 1) = i
6413     idxm(MatStencil_j, 1) = j
6414     idxm(MatStencil_k, 1) = k
6415     idxm(MatStencil_c, 1) = c
6416     etc
6417 .ve
6418 
6419 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6420           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6421 @*/
6422 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6423 {
6424   PetscInt  dim    = mat->stencil.dim;
6425   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6426   PetscInt *dims   = mat->stencil.dims + 1;
6427   PetscInt *starts = mat->stencil.starts;
6428   PetscInt *dxm    = (PetscInt *)rows;
6429   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6430 
6431   PetscFunctionBegin;
6432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6433   PetscValidType(mat, 1);
6434   if (numRows) PetscValidPointer(rows, 3);
6435 
6436   PetscCall(PetscMalloc1(numRows, &jdxm));
6437   for (i = 0; i < numRows; ++i) {
6438     /* Skip unused dimensions (they are ordered k, j, i, c) */
6439     for (j = 0; j < 3 - sdim; ++j) dxm++;
6440     /* Local index in X dir */
6441     tmp = *dxm++ - starts[0];
6442     /* Loop over remaining dimensions */
6443     for (j = 0; j < dim - 1; ++j) {
6444       /* If nonlocal, set index to be negative */
6445       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6446       /* Update local index */
6447       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6448     }
6449     /* Skip component slot if necessary */
6450     if (mat->stencil.noc) dxm++;
6451     /* Local row number */
6452     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6453   }
6454   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6455   PetscCall(PetscFree(jdxm));
6456   PetscFunctionReturn(PETSC_SUCCESS);
6457 }
6458 
6459 /*@C
6460    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6461    of a set of rows of a matrix; using local numbering of rows.
6462 
6463    Collective
6464 
6465    Input Parameters:
6466 +  mat - the matrix
6467 .  numRows - the number of rows to remove
6468 .  rows - the local row indices
6469 .  diag - value put in all diagonals of eliminated rows
6470 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6471 -  b - optional vector of right hand side, that will be adjusted by provided solution
6472 
6473    Level: intermediate
6474 
6475    Notes:
6476    Before calling `MatZeroRowsLocal()`, the user must first set the
6477    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6478 
6479    See `MatZeroRows()` for details on how this routine operates.
6480 
6481 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6482           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6483 @*/
6484 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6485 {
6486   PetscFunctionBegin;
6487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6488   PetscValidType(mat, 1);
6489   if (numRows) PetscValidIntPointer(rows, 3);
6490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6492   MatCheckPreallocated(mat, 1);
6493 
6494   if (mat->ops->zerorowslocal) {
6495     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6496   } else {
6497     IS              is, newis;
6498     const PetscInt *newRows;
6499 
6500     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6501     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6502     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6503     PetscCall(ISGetIndices(newis, &newRows));
6504     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6505     PetscCall(ISRestoreIndices(newis, &newRows));
6506     PetscCall(ISDestroy(&newis));
6507     PetscCall(ISDestroy(&is));
6508   }
6509   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6510   PetscFunctionReturn(PETSC_SUCCESS);
6511 }
6512 
6513 /*@
6514    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6515    of a set of rows of a matrix; using local numbering of rows.
6516 
6517    Collective
6518 
6519    Input Parameters:
6520 +  mat - the matrix
6521 .  is - index set of rows to remove
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 `MatZeroRowsLocalIS()`, 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 `MatZeroRows()` for details on how this routine operates.
6533 
6534 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6535           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6536 @*/
6537 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6538 {
6539   PetscInt        numRows;
6540   const PetscInt *rows;
6541 
6542   PetscFunctionBegin;
6543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6544   PetscValidType(mat, 1);
6545   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
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   PetscCall(ISGetLocalSize(is, &numRows));
6551   PetscCall(ISGetIndices(is, &rows));
6552   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6553   PetscCall(ISRestoreIndices(is, &rows));
6554   PetscFunctionReturn(PETSC_SUCCESS);
6555 }
6556 
6557 /*@
6558    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6559    of a set of rows and columns of a matrix; using local numbering of rows.
6560 
6561    Collective
6562 
6563    Input Parameters:
6564 +  mat - the matrix
6565 .  numRows - the number of rows to remove
6566 .  rows - the global row indices
6567 .  diag - value put in all diagonals of eliminated rows
6568 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6569 -  b - optional vector of right hand side, that will be adjusted by provided solution
6570 
6571    Level: intermediate
6572 
6573    Notes:
6574    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6575    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6576 
6577    See `MatZeroRowsColumns()` for details on how this routine operates.
6578 
6579 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6580           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6581 @*/
6582 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6583 {
6584   IS              is, newis;
6585   const PetscInt *newRows;
6586 
6587   PetscFunctionBegin;
6588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6589   PetscValidType(mat, 1);
6590   if (numRows) PetscValidIntPointer(rows, 3);
6591   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6592   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6593   MatCheckPreallocated(mat, 1);
6594 
6595   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6596   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6597   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6598   PetscCall(ISGetIndices(newis, &newRows));
6599   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6600   PetscCall(ISRestoreIndices(newis, &newRows));
6601   PetscCall(ISDestroy(&newis));
6602   PetscCall(ISDestroy(&is));
6603   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6604   PetscFunctionReturn(PETSC_SUCCESS);
6605 }
6606 
6607 /*@
6608    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6609    of a set of rows and columns of a matrix; using local numbering of rows.
6610 
6611    Collective
6612 
6613    Input Parameters:
6614 +  mat - the matrix
6615 .  is - index set of rows to remove
6616 .  diag - value put in all diagonals of eliminated rows
6617 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6618 -  b - optional vector of right hand side, that will be adjusted by provided solution
6619 
6620    Level: intermediate
6621 
6622    Notes:
6623    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6624    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6625 
6626    See `MatZeroRowsColumns()` for details on how this routine operates.
6627 
6628 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6629           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6630 @*/
6631 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6632 {
6633   PetscInt        numRows;
6634   const PetscInt *rows;
6635 
6636   PetscFunctionBegin;
6637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6638   PetscValidType(mat, 1);
6639   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6640   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6641   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6642   MatCheckPreallocated(mat, 1);
6643 
6644   PetscCall(ISGetLocalSize(is, &numRows));
6645   PetscCall(ISGetIndices(is, &rows));
6646   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6647   PetscCall(ISRestoreIndices(is, &rows));
6648   PetscFunctionReturn(PETSC_SUCCESS);
6649 }
6650 
6651 /*@C
6652    MatGetSize - Returns the numbers of rows and columns in a matrix.
6653 
6654    Not Collective
6655 
6656    Input Parameter:
6657 .  mat - the matrix
6658 
6659    Output Parameters:
6660 +  m - the number of global rows
6661 -  n - the number of global columns
6662 
6663    Level: beginner
6664 
6665    Note:
6666    Both output parameters can be `NULL` on input.
6667 
6668 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6669 @*/
6670 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6671 {
6672   PetscFunctionBegin;
6673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6674   if (m) *m = mat->rmap->N;
6675   if (n) *n = mat->cmap->N;
6676   PetscFunctionReturn(PETSC_SUCCESS);
6677 }
6678 
6679 /*@C
6680    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6681    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6682 
6683    Not Collective
6684 
6685    Input Parameter:
6686 .  mat - the matrix
6687 
6688    Output Parameters:
6689 +  m - the number of local rows, use `NULL` to not obtain this value
6690 -  n - the number of local columns, use `NULL` to not obtain this value
6691 
6692    Level: beginner
6693 
6694 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6695 @*/
6696 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6697 {
6698   PetscFunctionBegin;
6699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6700   if (m) PetscValidIntPointer(m, 2);
6701   if (n) PetscValidIntPointer(n, 3);
6702   if (m) *m = mat->rmap->n;
6703   if (n) *n = mat->cmap->n;
6704   PetscFunctionReturn(PETSC_SUCCESS);
6705 }
6706 
6707 /*@C
6708    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6709    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6710 
6711    Not Collective, unless matrix has not been allocated, then collective
6712 
6713    Input Parameter:
6714 .  mat - the matrix
6715 
6716    Output Parameters:
6717 +  m - the global index of the first local column, use `NULL` to not obtain this value
6718 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6719 
6720    Level: developer
6721 
6722 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6723 @*/
6724 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6725 {
6726   PetscFunctionBegin;
6727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6728   PetscValidType(mat, 1);
6729   if (m) PetscValidIntPointer(m, 2);
6730   if (n) PetscValidIntPointer(n, 3);
6731   MatCheckPreallocated(mat, 1);
6732   if (m) *m = mat->cmap->rstart;
6733   if (n) *n = mat->cmap->rend;
6734   PetscFunctionReturn(PETSC_SUCCESS);
6735 }
6736 
6737 /*@C
6738    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6739    this MPI process. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6740    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6741 
6742    Not Collective
6743 
6744    Input Parameter:
6745 .  mat - the matrix
6746 
6747    Output Parameters:
6748 +  m - the global index of the first local row, use `NULL` to not obtain this value
6749 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6750 
6751    Level: beginner
6752 
6753    Note:
6754   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6755   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6756   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6757 
6758 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6759           `PetscLayout`
6760 @*/
6761 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6762 {
6763   PetscFunctionBegin;
6764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6765   PetscValidType(mat, 1);
6766   if (m) PetscValidIntPointer(m, 2);
6767   if (n) PetscValidIntPointer(n, 3);
6768   MatCheckPreallocated(mat, 1);
6769   if (m) *m = mat->rmap->rstart;
6770   if (n) *n = mat->rmap->rend;
6771   PetscFunctionReturn(PETSC_SUCCESS);
6772 }
6773 
6774 /*@C
6775    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6776    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
6777    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6778 
6779    Not Collective, unless matrix has not been allocated
6780 
6781    Input Parameter:
6782 .  mat - the matrix
6783 
6784    Output Parameter:
6785 .  ranges - start of each processors portion plus one more than the total length at the end
6786 
6787    Level: beginner
6788 
6789 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6790 @*/
6791 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6792 {
6793   PetscFunctionBegin;
6794   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6795   PetscValidType(mat, 1);
6796   MatCheckPreallocated(mat, 1);
6797   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6798   PetscFunctionReturn(PETSC_SUCCESS);
6799 }
6800 
6801 /*@C
6802    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6803    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6804 
6805    Not Collective, unless matrix has not been allocated
6806 
6807    Input Parameter:
6808 .  mat - the matrix
6809 
6810    Output Parameter:
6811 .  ranges - start of each processors portion plus one more then the total length at the end
6812 
6813    Level: beginner
6814 
6815 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6816 @*/
6817 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6818 {
6819   PetscFunctionBegin;
6820   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6821   PetscValidType(mat, 1);
6822   MatCheckPreallocated(mat, 1);
6823   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6824   PetscFunctionReturn(PETSC_SUCCESS);
6825 }
6826 
6827 /*@C
6828    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6829    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6830    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6831 
6832    Not Collective
6833 
6834    Input Parameter:
6835 .  A - matrix
6836 
6837    Output Parameters:
6838 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6839 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6840 
6841    Level: intermediate
6842 
6843 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6844 @*/
6845 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6846 {
6847   PetscErrorCode (*f)(Mat, IS *, IS *);
6848 
6849   PetscFunctionBegin;
6850   MatCheckPreallocated(A, 1);
6851   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6852   if (f) {
6853     PetscCall((*f)(A, rows, cols));
6854   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6855     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6856     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6857   }
6858   PetscFunctionReturn(PETSC_SUCCESS);
6859 }
6860 
6861 /*@C
6862    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6863    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6864    to complete the factorization.
6865 
6866    Collective
6867 
6868    Input Parameters:
6869 +  fact - the factorized matrix obtained with `MatGetFactor()`
6870 .  mat - the matrix
6871 .  row - row permutation
6872 .  col - column permutation
6873 -  info - structure containing
6874 .vb
6875       levels - number of levels of fill.
6876       expected fill - as ratio of original fill.
6877       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6878                 missing diagonal entries)
6879 .ve
6880 
6881    Level: developer
6882 
6883    Notes:
6884    See [Matrix Factorization](sec_matfactor) for additional information.
6885 
6886    Most users should employ the `KSP` interface for linear solvers
6887    instead of working directly with matrix algebra routines such as this.
6888    See, e.g., `KSPCreate()`.
6889 
6890    Uses the definition of level of fill as in Y. Saad, 2003
6891 
6892    Developer Note:
6893    The Fortran interface is not autogenerated as the
6894    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6895 
6896    References:
6897 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6898 
6899 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6900           `MatGetOrdering()`, `MatFactorInfo`
6901 @*/
6902 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6903 {
6904   PetscFunctionBegin;
6905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6906   PetscValidType(mat, 2);
6907   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6908   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6909   PetscValidPointer(info, 5);
6910   PetscValidPointer(fact, 1);
6911   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6912   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6913   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6914   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6915   MatCheckPreallocated(mat, 2);
6916 
6917   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6918   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6919   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6920   PetscFunctionReturn(PETSC_SUCCESS);
6921 }
6922 
6923 /*@C
6924    MatICCFactorSymbolic - Performs symbolic incomplete
6925    Cholesky factorization for a symmetric matrix.  Use
6926    `MatCholeskyFactorNumeric()` to complete the factorization.
6927 
6928    Collective
6929 
6930    Input Parameters:
6931 +  fact - the factorized matrix obtained with `MatGetFactor()`
6932 .  mat - the matrix to be factored
6933 .  perm - row and column permutation
6934 -  info - structure containing
6935 .vb
6936       levels - number of levels of fill.
6937       expected fill - as ratio of original fill.
6938 .ve
6939 
6940    Level: developer
6941 
6942    Notes:
6943    Most users should employ the `KSP` interface for linear solvers
6944    instead of working directly with matrix algebra routines such as this.
6945    See, e.g., `KSPCreate()`.
6946 
6947    This uses the definition of level of fill as in Y. Saad, 2003
6948 
6949    Developer Note:
6950    The Fortran interface is not autogenerated as the
6951    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6952 
6953    References:
6954 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6955 
6956 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6957 @*/
6958 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6959 {
6960   PetscFunctionBegin;
6961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6962   PetscValidType(mat, 2);
6963   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6964   PetscValidPointer(info, 4);
6965   PetscValidPointer(fact, 1);
6966   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6967   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6968   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6969   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6970   MatCheckPreallocated(mat, 2);
6971 
6972   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6973   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6974   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6975   PetscFunctionReturn(PETSC_SUCCESS);
6976 }
6977 
6978 /*@C
6979    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6980    points to an array of valid matrices, they may be reused to store the new
6981    submatrices.
6982 
6983    Collective
6984 
6985    Input Parameters:
6986 +  mat - the matrix
6987 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6988 .  irow - index set of rows to extract
6989 .  icol - index set of columns to extract
6990 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6991 
6992    Output Parameter:
6993 .  submat - the array of submatrices
6994 
6995    Level: advanced
6996 
6997    Notes:
6998    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6999    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7000    to extract a parallel submatrix.
7001 
7002    Some matrix types place restrictions on the row and column
7003    indices, such as that they be sorted or that they be equal to each other.
7004 
7005    The index sets may not have duplicate entries.
7006 
7007    When extracting submatrices from a parallel matrix, each processor can
7008    form a different submatrix by setting the rows and columns of its
7009    individual index sets according to the local submatrix desired.
7010 
7011    When finished using the submatrices, the user should destroy
7012    them with `MatDestroySubMatrices()`.
7013 
7014    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7015    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7016 
7017    This routine creates the matrices in submat; you should NOT create them before
7018    calling it. It also allocates the array of matrix pointers submat.
7019 
7020    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7021    request one row/column in a block, they must request all rows/columns that are in
7022    that block. For example, if the block size is 2 you cannot request just row 0 and
7023    column 0.
7024 
7025    Fortran Note:
7026    The Fortran interface is slightly different from that given below; it
7027    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7028 
7029 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7030 @*/
7031 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7032 {
7033   PetscInt  i;
7034   PetscBool eq;
7035 
7036   PetscFunctionBegin;
7037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7038   PetscValidType(mat, 1);
7039   if (n) {
7040     PetscValidPointer(irow, 3);
7041     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7042     PetscValidPointer(icol, 4);
7043     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7044   }
7045   PetscValidPointer(submat, 6);
7046   if (n && scall == MAT_REUSE_MATRIX) {
7047     PetscValidPointer(*submat, 6);
7048     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7049   }
7050   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7051   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7052   MatCheckPreallocated(mat, 1);
7053   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7054   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7055   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7056   for (i = 0; i < n; i++) {
7057     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7058     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7059     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7060 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7061     if (mat->boundtocpu && mat->bindingpropagates) {
7062       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7063       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7064     }
7065 #endif
7066   }
7067   PetscFunctionReturn(PETSC_SUCCESS);
7068 }
7069 
7070 /*@C
7071    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7072 
7073    Collective
7074 
7075    Input Parameters:
7076 +  mat - the matrix
7077 .  n   - the number of submatrixes to be extracted
7078 .  irow - index set of rows to extract
7079 .  icol - index set of columns to extract
7080 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7081 
7082    Output Parameter:
7083 .  submat - the array of submatrices
7084 
7085    Level: advanced
7086 
7087    Note:
7088    This is used by `PCGASM`
7089 
7090 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7091 @*/
7092 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7093 {
7094   PetscInt  i;
7095   PetscBool eq;
7096 
7097   PetscFunctionBegin;
7098   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7099   PetscValidType(mat, 1);
7100   if (n) {
7101     PetscValidPointer(irow, 3);
7102     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7103     PetscValidPointer(icol, 4);
7104     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7105   }
7106   PetscValidPointer(submat, 6);
7107   if (n && scall == MAT_REUSE_MATRIX) {
7108     PetscValidPointer(*submat, 6);
7109     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7110   }
7111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7112   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7113   MatCheckPreallocated(mat, 1);
7114 
7115   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7116   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7117   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7118   for (i = 0; i < n; i++) {
7119     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7120     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7121   }
7122   PetscFunctionReturn(PETSC_SUCCESS);
7123 }
7124 
7125 /*@C
7126    MatDestroyMatrices - Destroys an array of matrices.
7127 
7128    Collective
7129 
7130    Input Parameters:
7131 +  n - the number of local matrices
7132 -  mat - the matrices (this is a pointer to the array of matrices)
7133 
7134    Level: advanced
7135 
7136     Note:
7137     Frees not only the matrices, but also the array that contains the matrices
7138 
7139     Fortran Note:
7140     This does not free the array.
7141 
7142 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7143 @*/
7144 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7145 {
7146   PetscInt i;
7147 
7148   PetscFunctionBegin;
7149   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7150   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7151   PetscValidPointer(mat, 2);
7152 
7153   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7154 
7155   /* memory is allocated even if n = 0 */
7156   PetscCall(PetscFree(*mat));
7157   PetscFunctionReturn(PETSC_SUCCESS);
7158 }
7159 
7160 /*@C
7161    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7162 
7163    Collective
7164 
7165    Input Parameters:
7166 +  n - the number of local matrices
7167 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7168                        sequence of `MatCreateSubMatrices()`)
7169 
7170    Level: advanced
7171 
7172     Note:
7173     Frees not only the matrices, but also the array that contains the matrices
7174 
7175     Fortran Note:
7176     This does not free the array.
7177 
7178 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7179 @*/
7180 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7181 {
7182   Mat mat0;
7183 
7184   PetscFunctionBegin;
7185   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7186   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7187   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7188   PetscValidPointer(mat, 2);
7189 
7190   mat0 = (*mat)[0];
7191   if (mat0 && mat0->ops->destroysubmatrices) {
7192     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7193   } else {
7194     PetscCall(MatDestroyMatrices(n, mat));
7195   }
7196   PetscFunctionReturn(PETSC_SUCCESS);
7197 }
7198 
7199 /*@C
7200    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7201 
7202    Collective
7203 
7204    Input Parameter:
7205 .  mat - the matrix
7206 
7207    Output Parameter:
7208 .  matstruct - the sequential matrix with the nonzero structure of mat
7209 
7210   Level: developer
7211 
7212 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7213 @*/
7214 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7215 {
7216   PetscFunctionBegin;
7217   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7218   PetscValidPointer(matstruct, 2);
7219 
7220   PetscValidType(mat, 1);
7221   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7222   MatCheckPreallocated(mat, 1);
7223 
7224   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7225   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7226   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7227   PetscFunctionReturn(PETSC_SUCCESS);
7228 }
7229 
7230 /*@C
7231    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7232 
7233    Collective
7234 
7235    Input Parameter:
7236 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7237                        sequence of `MatGetSeqNonzeroStructure()`)
7238 
7239    Level: advanced
7240 
7241     Note:
7242     Frees not only the matrices, but also the array that contains the matrices
7243 
7244 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7245 @*/
7246 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7247 {
7248   PetscFunctionBegin;
7249   PetscValidPointer(mat, 1);
7250   PetscCall(MatDestroy(mat));
7251   PetscFunctionReturn(PETSC_SUCCESS);
7252 }
7253 
7254 /*@
7255    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7256    replaces the index sets by larger ones that represent submatrices with
7257    additional overlap.
7258 
7259    Collective
7260 
7261    Input Parameters:
7262 +  mat - the matrix
7263 .  n   - the number of index sets
7264 .  is  - the array of index sets (these index sets will changed during the call)
7265 -  ov  - the additional overlap requested
7266 
7267    Options Database Key:
7268 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7269 
7270    Level: developer
7271 
7272    Note:
7273    The computed overlap preserves the matrix block sizes when the blocks are square.
7274    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7275    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7276 
7277 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7278 @*/
7279 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7280 {
7281   PetscInt i, bs, cbs;
7282 
7283   PetscFunctionBegin;
7284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7285   PetscValidType(mat, 1);
7286   PetscValidLogicalCollectiveInt(mat, n, 2);
7287   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7288   if (n) {
7289     PetscValidPointer(is, 3);
7290     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7291   }
7292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7293   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7294   MatCheckPreallocated(mat, 1);
7295 
7296   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7297   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7298   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7299   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7300   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7301   if (bs == cbs) {
7302     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7303   }
7304   PetscFunctionReturn(PETSC_SUCCESS);
7305 }
7306 
7307 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7308 
7309 /*@
7310    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7311    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7312    additional overlap.
7313 
7314    Collective
7315 
7316    Input Parameters:
7317 +  mat - the matrix
7318 .  n   - the number of index sets
7319 .  is  - the array of index sets (these index sets will changed during the call)
7320 -  ov  - the additional overlap requested
7321 
7322 `   Options Database Key:
7323 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7324 
7325    Level: developer
7326 
7327 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7328 @*/
7329 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7330 {
7331   PetscInt i;
7332 
7333   PetscFunctionBegin;
7334   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7335   PetscValidType(mat, 1);
7336   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7337   if (n) {
7338     PetscValidPointer(is, 3);
7339     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7340   }
7341   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7342   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7343   MatCheckPreallocated(mat, 1);
7344   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7345   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7346   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7347   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7348   PetscFunctionReturn(PETSC_SUCCESS);
7349 }
7350 
7351 /*@
7352    MatGetBlockSize - Returns the matrix block size.
7353 
7354    Not Collective
7355 
7356    Input Parameter:
7357 .  mat - the matrix
7358 
7359    Output Parameter:
7360 .  bs - block size
7361 
7362    Level: intermediate
7363 
7364    Notes:
7365     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7366 
7367    If the block size has not been set yet this routine returns 1.
7368 
7369 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7370 @*/
7371 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7372 {
7373   PetscFunctionBegin;
7374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7375   PetscValidIntPointer(bs, 2);
7376   *bs = PetscAbs(mat->rmap->bs);
7377   PetscFunctionReturn(PETSC_SUCCESS);
7378 }
7379 
7380 /*@
7381    MatGetBlockSizes - Returns the matrix block row and column sizes.
7382 
7383    Not Collective
7384 
7385    Input Parameter:
7386 .  mat - the matrix
7387 
7388    Output Parameters:
7389 +  rbs - row block size
7390 -  cbs - column block size
7391 
7392    Level: intermediate
7393 
7394    Notes:
7395     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7396     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7397 
7398    If a block size has not been set yet this routine returns 1.
7399 
7400 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7401 @*/
7402 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7403 {
7404   PetscFunctionBegin;
7405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7406   if (rbs) PetscValidIntPointer(rbs, 2);
7407   if (cbs) PetscValidIntPointer(cbs, 3);
7408   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7409   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7410   PetscFunctionReturn(PETSC_SUCCESS);
7411 }
7412 
7413 /*@
7414    MatSetBlockSize - Sets the matrix block size.
7415 
7416    Logically Collective
7417 
7418    Input Parameters:
7419 +  mat - the matrix
7420 -  bs - block size
7421 
7422    Level: intermediate
7423 
7424    Notes:
7425     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7426     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7427 
7428     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7429     is compatible with the matrix local sizes.
7430 
7431 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7432 @*/
7433 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7434 {
7435   PetscFunctionBegin;
7436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7437   PetscValidLogicalCollectiveInt(mat, bs, 2);
7438   PetscCall(MatSetBlockSizes(mat, bs, bs));
7439   PetscFunctionReturn(PETSC_SUCCESS);
7440 }
7441 
7442 typedef struct {
7443   PetscInt         n;
7444   IS              *is;
7445   Mat             *mat;
7446   PetscObjectState nonzerostate;
7447   Mat              C;
7448 } EnvelopeData;
7449 
7450 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7451 {
7452   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7453   PetscCall(PetscFree(edata->is));
7454   PetscCall(PetscFree(edata));
7455   return PETSC_SUCCESS;
7456 }
7457 
7458 /*
7459    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7460          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7461 
7462    Collective
7463 
7464    Input Parameter:
7465 .  mat - the matrix
7466 
7467    Notes:
7468      There can be zeros within the blocks
7469 
7470      The blocks can overlap between processes, including laying on more than two processes
7471 
7472 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7473 */
7474 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7475 {
7476   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7477   PetscInt          *diag, *odiag, sc;
7478   VecScatter         scatter;
7479   PetscScalar       *seqv;
7480   const PetscScalar *parv;
7481   const PetscInt    *ia, *ja;
7482   PetscBool          set, flag, done;
7483   Mat                AA = mat, A;
7484   MPI_Comm           comm;
7485   PetscMPIInt        rank, size, tag;
7486   MPI_Status         status;
7487   PetscContainer     container;
7488   EnvelopeData      *edata;
7489   Vec                seq, par;
7490   IS                 isglobal;
7491 
7492   PetscFunctionBegin;
7493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7494   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7495   if (!set || !flag) {
7496     /* TOO: only needs nonzero structure of transpose */
7497     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7498     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7499   }
7500   PetscCall(MatAIJGetLocalMat(AA, &A));
7501   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7502   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7503 
7504   PetscCall(MatGetLocalSize(mat, &n, NULL));
7505   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7506   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7507   PetscCallMPI(MPI_Comm_size(comm, &size));
7508   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7509 
7510   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7511 
7512   if (rank > 0) {
7513     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7514     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7515   }
7516   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7517   for (i = 0; i < n; i++) {
7518     env = PetscMax(env, ja[ia[i + 1] - 1]);
7519     II  = rstart + i;
7520     if (env == II) {
7521       starts[lblocks]  = tbs;
7522       sizes[lblocks++] = 1 + II - tbs;
7523       tbs              = 1 + II;
7524     }
7525   }
7526   if (rank < size - 1) {
7527     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7528     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7529   }
7530 
7531   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7532   if (!set || !flag) PetscCall(MatDestroy(&AA));
7533   PetscCall(MatDestroy(&A));
7534 
7535   PetscCall(PetscNew(&edata));
7536   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7537   edata->n = lblocks;
7538   /* create IS needed for extracting blocks from the original matrix */
7539   PetscCall(PetscMalloc1(lblocks, &edata->is));
7540   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7541 
7542   /* Create the resulting inverse matrix structure with preallocation information */
7543   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7544   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7545   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7546   PetscCall(MatSetType(edata->C, MATAIJ));
7547 
7548   /* Communicate the start and end of each row, from each block to the correct rank */
7549   /* TODO: Use PetscSF instead of VecScatter */
7550   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7551   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7552   PetscCall(VecGetArrayWrite(seq, &seqv));
7553   for (PetscInt i = 0; i < lblocks; i++) {
7554     for (PetscInt j = 0; j < sizes[i]; j++) {
7555       seqv[cnt]     = starts[i];
7556       seqv[cnt + 1] = starts[i] + sizes[i];
7557       cnt += 2;
7558     }
7559   }
7560   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7561   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7562   sc -= cnt;
7563   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7564   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7565   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7566   PetscCall(ISDestroy(&isglobal));
7567   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7568   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7569   PetscCall(VecScatterDestroy(&scatter));
7570   PetscCall(VecDestroy(&seq));
7571   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7572   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7573   PetscCall(VecGetArrayRead(par, &parv));
7574   cnt = 0;
7575   PetscCall(MatGetSize(mat, NULL, &n));
7576   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7577     PetscInt start, end, d = 0, od = 0;
7578 
7579     start = (PetscInt)PetscRealPart(parv[cnt]);
7580     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7581     cnt += 2;
7582 
7583     if (start < cstart) {
7584       od += cstart - start + n - cend;
7585       d += cend - cstart;
7586     } else if (start < cend) {
7587       od += n - cend;
7588       d += cend - start;
7589     } else od += n - start;
7590     if (end <= cstart) {
7591       od -= cstart - end + n - cend;
7592       d -= cend - cstart;
7593     } else if (end < cend) {
7594       od -= n - cend;
7595       d -= cend - end;
7596     } else od -= n - end;
7597 
7598     odiag[i] = od;
7599     diag[i]  = d;
7600   }
7601   PetscCall(VecRestoreArrayRead(par, &parv));
7602   PetscCall(VecDestroy(&par));
7603   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7604   PetscCall(PetscFree2(diag, odiag));
7605   PetscCall(PetscFree2(sizes, starts));
7606 
7607   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7608   PetscCall(PetscContainerSetPointer(container, edata));
7609   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7610   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7611   PetscCall(PetscObjectDereference((PetscObject)container));
7612   PetscFunctionReturn(PETSC_SUCCESS);
7613 }
7614 
7615 /*@
7616   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7617 
7618   Collective
7619 
7620   Input Parameters:
7621 + A - the matrix
7622 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7623 
7624   Output Parameter:
7625 . C - matrix with inverted block diagonal of `A`
7626 
7627   Level: advanced
7628 
7629   Note:
7630      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7631 
7632 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7633 @*/
7634 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7635 {
7636   PetscContainer   container;
7637   EnvelopeData    *edata;
7638   PetscObjectState nonzerostate;
7639 
7640   PetscFunctionBegin;
7641   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7642   if (!container) {
7643     PetscCall(MatComputeVariableBlockEnvelope(A));
7644     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7645   }
7646   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7647   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7648   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7649   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7650 
7651   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7652   *C = edata->C;
7653 
7654   for (PetscInt i = 0; i < edata->n; i++) {
7655     Mat          D;
7656     PetscScalar *dvalues;
7657 
7658     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7659     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7660     PetscCall(MatSeqDenseInvert(D));
7661     PetscCall(MatDenseGetArray(D, &dvalues));
7662     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7663     PetscCall(MatDestroy(&D));
7664   }
7665   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7666   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7667   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7668   PetscFunctionReturn(PETSC_SUCCESS);
7669 }
7670 
7671 /*@
7672    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7673 
7674    Logically Collective
7675 
7676    Input Parameters:
7677 +  mat - the matrix
7678 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7679 -  bsizes - the block sizes
7680 
7681    Level: intermediate
7682 
7683    Notes:
7684     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7685 
7686     Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes.
7687 
7688 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7689           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7690 @*/
7691 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7692 {
7693   PetscInt i, ncnt = 0, nlocal;
7694 
7695   PetscFunctionBegin;
7696   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7697   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7698   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7699   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7700   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);
7701   PetscCall(PetscFree(mat->bsizes));
7702   mat->nblocks = nblocks;
7703   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7704   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7705   PetscFunctionReturn(PETSC_SUCCESS);
7706 }
7707 
7708 /*@C
7709    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7710 
7711    Logically Collective; No Fortran Support
7712 
7713    Input Parameter:
7714 .  mat - the matrix
7715 
7716    Output Parameters:
7717 +  nblocks - the number of blocks on this process
7718 -  bsizes - the block sizes
7719 
7720    Level: intermediate
7721 
7722 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7723 @*/
7724 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7725 {
7726   PetscFunctionBegin;
7727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7728   *nblocks = mat->nblocks;
7729   *bsizes  = mat->bsizes;
7730   PetscFunctionReturn(PETSC_SUCCESS);
7731 }
7732 
7733 /*@
7734    MatSetBlockSizes - Sets the matrix block row and column sizes.
7735 
7736    Logically Collective
7737 
7738    Input Parameters:
7739 +  mat - the matrix
7740 .  rbs - row block size
7741 -  cbs - column block size
7742 
7743    Level: intermediate
7744 
7745    Notes:
7746     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7747     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7748     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7749 
7750     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7751     are compatible with the matrix local sizes.
7752 
7753     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7754 
7755 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7756 @*/
7757 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7758 {
7759   PetscFunctionBegin;
7760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7761   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7762   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7763   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7764   if (mat->rmap->refcnt) {
7765     ISLocalToGlobalMapping l2g  = NULL;
7766     PetscLayout            nmap = NULL;
7767 
7768     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7769     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7770     PetscCall(PetscLayoutDestroy(&mat->rmap));
7771     mat->rmap          = nmap;
7772     mat->rmap->mapping = l2g;
7773   }
7774   if (mat->cmap->refcnt) {
7775     ISLocalToGlobalMapping l2g  = NULL;
7776     PetscLayout            nmap = NULL;
7777 
7778     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7779     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7780     PetscCall(PetscLayoutDestroy(&mat->cmap));
7781     mat->cmap          = nmap;
7782     mat->cmap->mapping = l2g;
7783   }
7784   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7785   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7786   PetscFunctionReturn(PETSC_SUCCESS);
7787 }
7788 
7789 /*@
7790    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7791 
7792    Logically Collective
7793 
7794    Input Parameters:
7795 +  mat - the matrix
7796 .  fromRow - matrix from which to copy row block size
7797 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7798 
7799    Level: developer
7800 
7801 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7802 @*/
7803 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7804 {
7805   PetscFunctionBegin;
7806   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7807   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7808   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7809   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7810   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7811   PetscFunctionReturn(PETSC_SUCCESS);
7812 }
7813 
7814 /*@
7815    MatResidual - Default routine to calculate the residual r = b - Ax
7816 
7817    Collective
7818 
7819    Input Parameters:
7820 +  mat - the matrix
7821 .  b   - the right-hand-side
7822 -  x   - the approximate solution
7823 
7824    Output Parameter:
7825 .  r - location to store the residual
7826 
7827    Level: developer
7828 
7829 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7830 @*/
7831 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7832 {
7833   PetscFunctionBegin;
7834   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7835   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7836   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7837   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7838   PetscValidType(mat, 1);
7839   MatCheckPreallocated(mat, 1);
7840   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7841   if (!mat->ops->residual) {
7842     PetscCall(MatMult(mat, x, r));
7843     PetscCall(VecAYPX(r, -1.0, b));
7844   } else {
7845     PetscUseTypeMethod(mat, residual, b, x, r);
7846   }
7847   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7848   PetscFunctionReturn(PETSC_SUCCESS);
7849 }
7850 
7851 /*MC
7852     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7853 
7854     Synopsis:
7855     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7856 
7857     Not Collective
7858 
7859     Input Parameters:
7860 +   A - the matrix
7861 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7862 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7863 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7864                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7865                  always used.
7866 
7867     Output Parameters:
7868 +   n - number of local rows in the (possibly compressed) matrix
7869 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7870 .   ja - the column indices
7871 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7872            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7873 
7874     Level: developer
7875 
7876     Note:
7877     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7878 
7879 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7880 M*/
7881 
7882 /*MC
7883     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7884 
7885     Synopsis:
7886     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7887 
7888     Not Collective
7889 
7890     Input Parameters:
7891 +   A - the  matrix
7892 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7893 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7894     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7895                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7896                  always used.
7897 .   n - number of local rows in the (possibly compressed) matrix
7898 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7899 .   ja - the column indices
7900 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7901            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7902 
7903     Level: developer
7904 
7905 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7906 M*/
7907 
7908 /*@C
7909     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7910 
7911    Collective
7912 
7913     Input Parameters:
7914 +   mat - the matrix
7915 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7916 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7917 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7918                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7919                  always used.
7920 
7921     Output Parameters:
7922 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7923 .   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
7924 .   ja - the column indices, use `NULL` if not needed
7925 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7926            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7927 
7928     Level: developer
7929 
7930     Notes:
7931     You CANNOT change any of the ia[] or ja[] values.
7932 
7933     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7934 
7935     Fortran Notes:
7936     Use
7937 .vb
7938     PetscInt, pointer :: ia(:),ja(:)
7939     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7940     ! Access the ith and jth entries via ia(i) and ja(j)
7941 .ve
7942    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7943 
7944 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7945 @*/
7946 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7947 {
7948   PetscFunctionBegin;
7949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7950   PetscValidType(mat, 1);
7951   if (n) PetscValidIntPointer(n, 5);
7952   if (ia) PetscValidPointer(ia, 6);
7953   if (ja) PetscValidPointer(ja, 7);
7954   if (done) PetscValidBoolPointer(done, 8);
7955   MatCheckPreallocated(mat, 1);
7956   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7957   else {
7958     if (done) *done = PETSC_TRUE;
7959     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7960     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7961     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7962   }
7963   PetscFunctionReturn(PETSC_SUCCESS);
7964 }
7965 
7966 /*@C
7967     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7968 
7969     Collective
7970 
7971     Input Parameters:
7972 +   mat - the matrix
7973 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7974 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7975                 symmetrized
7976 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7977                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7978                  always used.
7979 .   n - number of columns in the (possibly compressed) matrix
7980 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7981 -   ja - the row indices
7982 
7983     Output Parameter:
7984 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7985 
7986     Level: developer
7987 
7988 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7989 @*/
7990 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7991 {
7992   PetscFunctionBegin;
7993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7994   PetscValidType(mat, 1);
7995   PetscValidIntPointer(n, 5);
7996   if (ia) PetscValidPointer(ia, 6);
7997   if (ja) PetscValidPointer(ja, 7);
7998   PetscValidBoolPointer(done, 8);
7999   MatCheckPreallocated(mat, 1);
8000   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8001   else {
8002     *done = PETSC_TRUE;
8003     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8004   }
8005   PetscFunctionReturn(PETSC_SUCCESS);
8006 }
8007 
8008 /*@C
8009     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8010 
8011     Collective
8012 
8013     Input Parameters:
8014 +   mat - the matrix
8015 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8016 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8017 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8018                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8019                  always used.
8020 .   n - size of (possibly compressed) matrix
8021 .   ia - the row pointers
8022 -   ja - the column indices
8023 
8024     Output Parameter:
8025 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8026 
8027     Level: developer
8028 
8029     Note:
8030     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8031     us of the array after it has been restored. If you pass `NULL`, it will
8032     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8033 
8034     Fortran Note:
8035    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8036 
8037 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8038 @*/
8039 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8040 {
8041   PetscFunctionBegin;
8042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8043   PetscValidType(mat, 1);
8044   if (ia) PetscValidPointer(ia, 6);
8045   if (ja) PetscValidPointer(ja, 7);
8046   if (done) PetscValidBoolPointer(done, 8);
8047   MatCheckPreallocated(mat, 1);
8048 
8049   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8050   else {
8051     if (done) *done = PETSC_TRUE;
8052     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8053     if (n) *n = 0;
8054     if (ia) *ia = NULL;
8055     if (ja) *ja = NULL;
8056   }
8057   PetscFunctionReturn(PETSC_SUCCESS);
8058 }
8059 
8060 /*@C
8061     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8062 
8063     Collective
8064 
8065     Input Parameters:
8066 +   mat - the matrix
8067 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8068 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8069 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8070                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8071                  always used.
8072 
8073     Output Parameters:
8074 +   n - size of (possibly compressed) matrix
8075 .   ia - the column pointers
8076 .   ja - the row indices
8077 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8078 
8079     Level: developer
8080 
8081 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8082 @*/
8083 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8084 {
8085   PetscFunctionBegin;
8086   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8087   PetscValidType(mat, 1);
8088   if (ia) PetscValidPointer(ia, 6);
8089   if (ja) PetscValidPointer(ja, 7);
8090   PetscValidBoolPointer(done, 8);
8091   MatCheckPreallocated(mat, 1);
8092 
8093   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8094   else {
8095     *done = PETSC_TRUE;
8096     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8097     if (n) *n = 0;
8098     if (ia) *ia = NULL;
8099     if (ja) *ja = NULL;
8100   }
8101   PetscFunctionReturn(PETSC_SUCCESS);
8102 }
8103 
8104 /*@C
8105     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8106 
8107     Collective
8108 
8109     Input Parameters:
8110 +   mat - the matrix
8111 .   ncolors - maximum color value
8112 .   n   - number of entries in colorarray
8113 -   colorarray - array indicating color for each column
8114 
8115     Output Parameter:
8116 .   iscoloring - coloring generated using colorarray information
8117 
8118     Level: developer
8119 
8120 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8121 @*/
8122 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8123 {
8124   PetscFunctionBegin;
8125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8126   PetscValidType(mat, 1);
8127   PetscValidIntPointer(colorarray, 4);
8128   PetscValidPointer(iscoloring, 5);
8129   MatCheckPreallocated(mat, 1);
8130 
8131   if (!mat->ops->coloringpatch) {
8132     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8133   } else {
8134     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8135   }
8136   PetscFunctionReturn(PETSC_SUCCESS);
8137 }
8138 
8139 /*@
8140    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8141 
8142    Logically Collective
8143 
8144    Input Parameter:
8145 .  mat - the factored matrix to be reset
8146 
8147    Level: developer
8148 
8149    Notes:
8150    This routine should be used only with factored matrices formed by in-place
8151    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8152    format).  This option can save memory, for example, when solving nonlinear
8153    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8154    ILU(0) preconditioner.
8155 
8156    One can specify in-place ILU(0) factorization by calling
8157 .vb
8158      PCType(pc,PCILU);
8159      PCFactorSeUseInPlace(pc);
8160 .ve
8161    or by using the options -pc_type ilu -pc_factor_in_place
8162 
8163    In-place factorization ILU(0) can also be used as a local
8164    solver for the blocks within the block Jacobi or additive Schwarz
8165    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8166    for details on setting local solver options.
8167 
8168    Most users should employ the `KSP` interface for linear solvers
8169    instead of working directly with matrix algebra routines such as this.
8170    See, e.g., `KSPCreate()`.
8171 
8172 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8173 @*/
8174 PetscErrorCode MatSetUnfactored(Mat mat)
8175 {
8176   PetscFunctionBegin;
8177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8178   PetscValidType(mat, 1);
8179   MatCheckPreallocated(mat, 1);
8180   mat->factortype = MAT_FACTOR_NONE;
8181   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8182   PetscUseTypeMethod(mat, setunfactored);
8183   PetscFunctionReturn(PETSC_SUCCESS);
8184 }
8185 
8186 /*MC
8187     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8188 
8189     Synopsis:
8190     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8191 
8192     Not Collective
8193 
8194     Input Parameter:
8195 .   x - matrix
8196 
8197     Output Parameters:
8198 +   xx_v - the Fortran pointer to the array
8199 -   ierr - error code
8200 
8201     Example of Usage:
8202 .vb
8203       PetscScalar, pointer xx_v(:,:)
8204       ....
8205       call MatDenseGetArrayF90(x,xx_v,ierr)
8206       a = xx_v(3)
8207       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8208 .ve
8209 
8210     Level: advanced
8211 
8212 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8213 M*/
8214 
8215 /*MC
8216     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8217     accessed with `MatDenseGetArrayF90()`.
8218 
8219     Synopsis:
8220     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8221 
8222     Not Collective
8223 
8224     Input Parameters:
8225 +   x - matrix
8226 -   xx_v - the Fortran90 pointer to the array
8227 
8228     Output Parameter:
8229 .   ierr - error code
8230 
8231     Example of Usage:
8232 .vb
8233        PetscScalar, pointer xx_v(:,:)
8234        ....
8235        call MatDenseGetArrayF90(x,xx_v,ierr)
8236        a = xx_v(3)
8237        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8238 .ve
8239 
8240     Level: advanced
8241 
8242 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8243 M*/
8244 
8245 /*MC
8246     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8247 
8248     Synopsis:
8249     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8250 
8251     Not Collective
8252 
8253     Input Parameter:
8254 .   x - matrix
8255 
8256     Output Parameters:
8257 +   xx_v - the Fortran pointer to the array
8258 -   ierr - error code
8259 
8260     Example of Usage:
8261 .vb
8262       PetscScalar, pointer xx_v(:)
8263       ....
8264       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8265       a = xx_v(3)
8266       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8267 .ve
8268 
8269     Level: advanced
8270 
8271 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8272 M*/
8273 
8274 /*MC
8275     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8276     accessed with `MatSeqAIJGetArrayF90()`.
8277 
8278     Synopsis:
8279     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8280 
8281     Not Collective
8282 
8283     Input Parameters:
8284 +   x - matrix
8285 -   xx_v - the Fortran90 pointer to the array
8286 
8287     Output Parameter:
8288 .   ierr - error code
8289 
8290     Example of Usage:
8291 .vb
8292        PetscScalar, pointer xx_v(:)
8293        ....
8294        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8295        a = xx_v(3)
8296        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8297 .ve
8298 
8299     Level: advanced
8300 
8301 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8302 M*/
8303 
8304 /*@
8305     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8306                       as the original matrix.
8307 
8308     Collective
8309 
8310     Input Parameters:
8311 +   mat - the original matrix
8312 .   isrow - parallel `IS` containing the rows this processor should obtain
8313 .   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.
8314 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8315 
8316     Output Parameter:
8317 .   newmat - the new submatrix, of the same type as the original matrix
8318 
8319     Level: advanced
8320 
8321     Notes:
8322     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8323 
8324     Some matrix types place restrictions on the row and column indices, such
8325     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;
8326     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8327 
8328     The index sets may not have duplicate entries.
8329 
8330       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8331    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8332    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8333    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8334    you are finished using it.
8335 
8336     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8337     the input matrix.
8338 
8339     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8340 
8341    Example usage:
8342    Consider the following 8x8 matrix with 34 non-zero values, that is
8343    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8344    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8345    as follows
8346 .vb
8347             1  2  0  |  0  3  0  |  0  4
8348     Proc0   0  5  6  |  7  0  0  |  8  0
8349             9  0 10  | 11  0  0  | 12  0
8350     -------------------------------------
8351            13  0 14  | 15 16 17  |  0  0
8352     Proc1   0 18  0  | 19 20 21  |  0  0
8353             0  0  0  | 22 23  0  | 24  0
8354     -------------------------------------
8355     Proc2  25 26 27  |  0  0 28  | 29  0
8356            30  0  0  | 31 32 33  |  0 34
8357 .ve
8358 
8359     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8360 
8361 .vb
8362             2  0  |  0  3  0  |  0
8363     Proc0   5  6  |  7  0  0  |  8
8364     -------------------------------
8365     Proc1  18  0  | 19 20 21  |  0
8366     -------------------------------
8367     Proc2  26 27  |  0  0 28  | 29
8368             0  0  | 31 32 33  |  0
8369 .ve
8370 
8371 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8372 @*/
8373 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8374 {
8375   PetscMPIInt size;
8376   Mat        *local;
8377   IS          iscoltmp;
8378   PetscBool   flg;
8379 
8380   PetscFunctionBegin;
8381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8382   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8383   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8384   PetscValidPointer(newmat, 5);
8385   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8386   PetscValidType(mat, 1);
8387   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8388   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8389 
8390   MatCheckPreallocated(mat, 1);
8391   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8392 
8393   if (!iscol || isrow == iscol) {
8394     PetscBool   stride;
8395     PetscMPIInt grabentirematrix = 0, grab;
8396     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8397     if (stride) {
8398       PetscInt first, step, n, rstart, rend;
8399       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8400       if (step == 1) {
8401         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8402         if (rstart == first) {
8403           PetscCall(ISGetLocalSize(isrow, &n));
8404           if (n == rend - rstart) grabentirematrix = 1;
8405         }
8406       }
8407     }
8408     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8409     if (grab) {
8410       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8411       if (cll == MAT_INITIAL_MATRIX) {
8412         *newmat = mat;
8413         PetscCall(PetscObjectReference((PetscObject)mat));
8414       }
8415       PetscFunctionReturn(PETSC_SUCCESS);
8416     }
8417   }
8418 
8419   if (!iscol) {
8420     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8421   } else {
8422     iscoltmp = iscol;
8423   }
8424 
8425   /* if original matrix is on just one processor then use submatrix generated */
8426   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8427     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8428     goto setproperties;
8429   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8430     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8431     *newmat = *local;
8432     PetscCall(PetscFree(local));
8433     goto setproperties;
8434   } else if (!mat->ops->createsubmatrix) {
8435     /* Create a new matrix type that implements the operation using the full matrix */
8436     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8437     switch (cll) {
8438     case MAT_INITIAL_MATRIX:
8439       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8440       break;
8441     case MAT_REUSE_MATRIX:
8442       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8443       break;
8444     default:
8445       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8446     }
8447     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8448     goto setproperties;
8449   }
8450 
8451   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8452   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8453   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8454 
8455 setproperties:
8456   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8457   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8458   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8459   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8460   PetscFunctionReturn(PETSC_SUCCESS);
8461 }
8462 
8463 /*@
8464    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8465 
8466    Not Collective
8467 
8468    Input Parameters:
8469 +  A - the matrix we wish to propagate options from
8470 -  B - the matrix we wish to propagate options to
8471 
8472    Level: beginner
8473 
8474    Note:
8475    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8476 
8477 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8478 @*/
8479 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8480 {
8481   PetscFunctionBegin;
8482   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8483   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8484   B->symmetry_eternal            = A->symmetry_eternal;
8485   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8486   B->symmetric                   = A->symmetric;
8487   B->structurally_symmetric      = A->structurally_symmetric;
8488   B->spd                         = A->spd;
8489   B->hermitian                   = A->hermitian;
8490   PetscFunctionReturn(PETSC_SUCCESS);
8491 }
8492 
8493 /*@
8494    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8495    used during the assembly process to store values that belong to
8496    other processors.
8497 
8498    Not Collective
8499 
8500    Input Parameters:
8501 +  mat   - the matrix
8502 .  size  - the initial size of the stash.
8503 -  bsize - the initial size of the block-stash(if used).
8504 
8505    Options Database Keys:
8506 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8507 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8508 
8509    Level: intermediate
8510 
8511    Notes:
8512      The block-stash is used for values set with `MatSetValuesBlocked()` while
8513      the stash is used for values set with `MatSetValues()`
8514 
8515      Run with the option -info and look for output of the form
8516      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8517      to determine the appropriate value, MM, to use for size and
8518      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8519      to determine the value, BMM to use for bsize
8520 
8521 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8522 @*/
8523 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8524 {
8525   PetscFunctionBegin;
8526   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8527   PetscValidType(mat, 1);
8528   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8529   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8530   PetscFunctionReturn(PETSC_SUCCESS);
8531 }
8532 
8533 /*@
8534    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8535      the matrix
8536 
8537    Neighbor-wise Collective
8538 
8539    Input Parameters:
8540 +  mat   - the matrix
8541 .  x - the vector to be multiplied by the interpolation operator
8542 -  y - the vector to be added to the result
8543 
8544    Output Parameter:
8545 .  w - the resulting vector
8546 
8547    Level: intermediate
8548 
8549    Notes:
8550     `w` may be the same vector as `y`.
8551 
8552     This allows one to use either the restriction or interpolation (its transpose)
8553     matrix to do the interpolation
8554 
8555 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8556 @*/
8557 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8558 {
8559   PetscInt M, N, Ny;
8560 
8561   PetscFunctionBegin;
8562   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8563   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8564   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8565   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8566   PetscCall(MatGetSize(A, &M, &N));
8567   PetscCall(VecGetSize(y, &Ny));
8568   if (M == Ny) {
8569     PetscCall(MatMultAdd(A, x, y, w));
8570   } else {
8571     PetscCall(MatMultTransposeAdd(A, x, y, w));
8572   }
8573   PetscFunctionReturn(PETSC_SUCCESS);
8574 }
8575 
8576 /*@
8577    MatInterpolate - y = A*x or A'*x depending on the shape of
8578      the matrix
8579 
8580    Neighbor-wise Collective
8581 
8582    Input Parameters:
8583 +  mat   - the matrix
8584 -  x - the vector to be interpolated
8585 
8586    Output Parameter:
8587 .  y - the resulting vector
8588 
8589    Level: intermediate
8590 
8591    Note:
8592     This allows one to use either the restriction or interpolation (its transpose)
8593     matrix to do the interpolation
8594 
8595 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8596 @*/
8597 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8598 {
8599   PetscInt M, N, Ny;
8600 
8601   PetscFunctionBegin;
8602   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8603   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8604   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8605   PetscCall(MatGetSize(A, &M, &N));
8606   PetscCall(VecGetSize(y, &Ny));
8607   if (M == Ny) {
8608     PetscCall(MatMult(A, x, y));
8609   } else {
8610     PetscCall(MatMultTranspose(A, x, y));
8611   }
8612   PetscFunctionReturn(PETSC_SUCCESS);
8613 }
8614 
8615 /*@
8616    MatRestrict - y = A*x or A'*x
8617 
8618    Neighbor-wise Collective
8619 
8620    Input Parameters:
8621 +  mat   - the matrix
8622 -  x - the vector to be restricted
8623 
8624    Output Parameter:
8625 .  y - the resulting vector
8626 
8627    Level: intermediate
8628 
8629    Note:
8630     This allows one to use either the restriction or interpolation (its transpose)
8631     matrix to do the restriction
8632 
8633 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8634 @*/
8635 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8636 {
8637   PetscInt M, N, Ny;
8638 
8639   PetscFunctionBegin;
8640   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8641   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8642   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8643   PetscCall(MatGetSize(A, &M, &N));
8644   PetscCall(VecGetSize(y, &Ny));
8645   if (M == Ny) {
8646     PetscCall(MatMult(A, x, y));
8647   } else {
8648     PetscCall(MatMultTranspose(A, x, y));
8649   }
8650   PetscFunctionReturn(PETSC_SUCCESS);
8651 }
8652 
8653 /*@
8654    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8655 
8656    Neighbor-wise Collective
8657 
8658    Input Parameters:
8659 +  mat   - the matrix
8660 .  x - the input dense matrix to be multiplied
8661 -  w - the input dense matrix to be added to the result
8662 
8663    Output Parameter:
8664 .  y - the output dense matrix
8665 
8666    Level: intermediate
8667 
8668    Note:
8669     This allows one to use either the restriction or interpolation (its transpose)
8670     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8671     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8672 
8673 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8674 @*/
8675 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8676 {
8677   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8678   PetscBool trans = PETSC_TRUE;
8679   MatReuse  reuse = MAT_INITIAL_MATRIX;
8680 
8681   PetscFunctionBegin;
8682   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8683   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8684   PetscValidType(x, 2);
8685   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8686   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8687   PetscCall(MatGetSize(A, &M, &N));
8688   PetscCall(MatGetSize(x, &Mx, &Nx));
8689   if (N == Mx) trans = PETSC_FALSE;
8690   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);
8691   Mo = trans ? N : M;
8692   if (*y) {
8693     PetscCall(MatGetSize(*y, &My, &Ny));
8694     if (Mo == My && Nx == Ny) {
8695       reuse = MAT_REUSE_MATRIX;
8696     } else {
8697       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);
8698       PetscCall(MatDestroy(y));
8699     }
8700   }
8701 
8702   if (w && *y == w) { /* this is to minimize changes in PCMG */
8703     PetscBool flg;
8704 
8705     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8706     if (w) {
8707       PetscInt My, Ny, Mw, Nw;
8708 
8709       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8710       PetscCall(MatGetSize(*y, &My, &Ny));
8711       PetscCall(MatGetSize(w, &Mw, &Nw));
8712       if (!flg || My != Mw || Ny != Nw) w = NULL;
8713     }
8714     if (!w) {
8715       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8716       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8717       PetscCall(PetscObjectDereference((PetscObject)w));
8718     } else {
8719       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8720     }
8721   }
8722   if (!trans) {
8723     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8724   } else {
8725     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8726   }
8727   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8728   PetscFunctionReturn(PETSC_SUCCESS);
8729 }
8730 
8731 /*@
8732    MatMatInterpolate - Y = A*X or A'*X
8733 
8734    Neighbor-wise Collective
8735 
8736    Input Parameters:
8737 +  mat   - the matrix
8738 -  x - the input dense matrix
8739 
8740    Output Parameter:
8741 .  y - the output dense matrix
8742 
8743    Level: intermediate
8744 
8745    Note:
8746     This allows one to use either the restriction or interpolation (its transpose)
8747     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8748     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8749 
8750 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8751 @*/
8752 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8753 {
8754   PetscFunctionBegin;
8755   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8756   PetscFunctionReturn(PETSC_SUCCESS);
8757 }
8758 
8759 /*@
8760    MatMatRestrict - Y = A*X or A'*X
8761 
8762    Neighbor-wise Collective
8763 
8764    Input Parameters:
8765 +  mat   - the matrix
8766 -  x - the input dense matrix
8767 
8768    Output Parameter:
8769 .  y - the output dense matrix
8770 
8771    Level: intermediate
8772 
8773    Note:
8774     This allows one to use either the restriction or interpolation (its transpose)
8775     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8776     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8777 
8778 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8779 @*/
8780 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8781 {
8782   PetscFunctionBegin;
8783   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8784   PetscFunctionReturn(PETSC_SUCCESS);
8785 }
8786 
8787 /*@
8788    MatGetNullSpace - retrieves the null space of a matrix.
8789 
8790    Logically Collective
8791 
8792    Input Parameters:
8793 +  mat - the matrix
8794 -  nullsp - the null space object
8795 
8796    Level: developer
8797 
8798 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8799 @*/
8800 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8801 {
8802   PetscFunctionBegin;
8803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8804   PetscValidPointer(nullsp, 2);
8805   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8806   PetscFunctionReturn(PETSC_SUCCESS);
8807 }
8808 
8809 /*@
8810    MatSetNullSpace - attaches a null space to a matrix.
8811 
8812    Logically Collective
8813 
8814    Input Parameters:
8815 +  mat - the matrix
8816 -  nullsp - the null space object
8817 
8818    Level: advanced
8819 
8820    Notes:
8821       This null space is used by the `KSP` linear solvers to solve singular systems.
8822 
8823       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`
8824 
8825       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
8826       to zero but the linear system will still be solved in a least squares sense.
8827 
8828       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8829    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).
8830    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
8831    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
8832    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).
8833    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8834 
8835     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8836     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8837     routine also automatically calls `MatSetTransposeNullSpace()`.
8838 
8839     The user should call `MatNullSpaceDestroy()`.
8840 
8841 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8842           `KSPSetPCSide()`
8843 @*/
8844 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8845 {
8846   PetscFunctionBegin;
8847   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8848   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8849   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8850   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8851   mat->nullsp = nullsp;
8852   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8853   PetscFunctionReturn(PETSC_SUCCESS);
8854 }
8855 
8856 /*@
8857    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8858 
8859    Logically Collective
8860 
8861    Input Parameters:
8862 +  mat - the matrix
8863 -  nullsp - the null space object
8864 
8865    Level: developer
8866 
8867 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8868 @*/
8869 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8870 {
8871   PetscFunctionBegin;
8872   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8873   PetscValidType(mat, 1);
8874   PetscValidPointer(nullsp, 2);
8875   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8876   PetscFunctionReturn(PETSC_SUCCESS);
8877 }
8878 
8879 /*@
8880    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8881 
8882    Logically Collective
8883 
8884    Input Parameters:
8885 +  mat - the matrix
8886 -  nullsp - the null space object
8887 
8888    Level: advanced
8889 
8890    Notes:
8891    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8892 
8893    See `MatSetNullSpace()`
8894 
8895 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8896 @*/
8897 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8898 {
8899   PetscFunctionBegin;
8900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8901   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8902   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8903   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8904   mat->transnullsp = nullsp;
8905   PetscFunctionReturn(PETSC_SUCCESS);
8906 }
8907 
8908 /*@
8909    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8910         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8911 
8912    Logically Collective
8913 
8914    Input Parameters:
8915 +  mat - the matrix
8916 -  nullsp - the null space object
8917 
8918    Level: advanced
8919 
8920    Notes:
8921    Overwrites any previous near null space that may have been attached
8922 
8923    You can remove the null space by calling this routine with an nullsp of `NULL`
8924 
8925 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8926 @*/
8927 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8928 {
8929   PetscFunctionBegin;
8930   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8931   PetscValidType(mat, 1);
8932   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8933   MatCheckPreallocated(mat, 1);
8934   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8935   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8936   mat->nearnullsp = nullsp;
8937   PetscFunctionReturn(PETSC_SUCCESS);
8938 }
8939 
8940 /*@
8941    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8942 
8943    Not Collective
8944 
8945    Input Parameter:
8946 .  mat - the matrix
8947 
8948    Output Parameter:
8949 .  nullsp - the null space object, `NULL` if not set
8950 
8951    Level: advanced
8952 
8953 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8954 @*/
8955 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8956 {
8957   PetscFunctionBegin;
8958   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8959   PetscValidType(mat, 1);
8960   PetscValidPointer(nullsp, 2);
8961   MatCheckPreallocated(mat, 1);
8962   *nullsp = mat->nearnullsp;
8963   PetscFunctionReturn(PETSC_SUCCESS);
8964 }
8965 
8966 /*@C
8967    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8968 
8969    Collective
8970 
8971    Input Parameters:
8972 +  mat - the matrix
8973 .  row - row/column permutation
8974 -  info - information on desired factorization process
8975 
8976    Level: developer
8977 
8978    Notes:
8979    Probably really in-place only when level of fill is zero, otherwise allocates
8980    new space to store factored matrix and deletes previous memory.
8981 
8982    Most users should employ the `KSP` interface for linear solvers
8983    instead of working directly with matrix algebra routines such as this.
8984    See, e.g., `KSPCreate()`.
8985 
8986    Developer Note:
8987    The Fortran interface is not autogenerated as the
8988    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8989 
8990 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8991 @*/
8992 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8993 {
8994   PetscFunctionBegin;
8995   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8996   PetscValidType(mat, 1);
8997   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8998   PetscValidPointer(info, 3);
8999   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9000   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9001   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9002   MatCheckPreallocated(mat, 1);
9003   PetscUseTypeMethod(mat, iccfactor, row, info);
9004   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9005   PetscFunctionReturn(PETSC_SUCCESS);
9006 }
9007 
9008 /*@
9009    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9010          ghosted ones.
9011 
9012    Not Collective
9013 
9014    Input Parameters:
9015 +  mat - the matrix
9016 -  diag - the diagonal values, including ghost ones
9017 
9018    Level: developer
9019 
9020    Notes:
9021     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9022 
9023     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9024 
9025 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9026 @*/
9027 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9028 {
9029   PetscMPIInt size;
9030 
9031   PetscFunctionBegin;
9032   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9033   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9034   PetscValidType(mat, 1);
9035 
9036   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9037   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9038   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9039   if (size == 1) {
9040     PetscInt n, m;
9041     PetscCall(VecGetSize(diag, &n));
9042     PetscCall(MatGetSize(mat, NULL, &m));
9043     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9044     PetscCall(MatDiagonalScale(mat, NULL, diag));
9045   } else {
9046     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9047   }
9048   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9049   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9050   PetscFunctionReturn(PETSC_SUCCESS);
9051 }
9052 
9053 /*@
9054    MatGetInertia - Gets the inertia from a factored matrix
9055 
9056    Collective
9057 
9058    Input Parameter:
9059 .  mat - the matrix
9060 
9061    Output Parameters:
9062 +   nneg - number of negative eigenvalues
9063 .   nzero - number of zero eigenvalues
9064 -   npos - number of positive eigenvalues
9065 
9066    Level: advanced
9067 
9068    Note:
9069     Matrix must have been factored by `MatCholeskyFactor()`
9070 
9071 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9072 @*/
9073 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9074 {
9075   PetscFunctionBegin;
9076   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9077   PetscValidType(mat, 1);
9078   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9079   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9080   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9081   PetscFunctionReturn(PETSC_SUCCESS);
9082 }
9083 
9084 /*@C
9085    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9086 
9087    Neighbor-wise Collective
9088 
9089    Input Parameters:
9090 +  mat - the factored matrix obtained with `MatGetFactor()`
9091 -  b - the right-hand-side vectors
9092 
9093    Output Parameter:
9094 .  x - the result vectors
9095 
9096    Level: developer
9097 
9098    Note:
9099    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9100    call `MatSolves`(A,x,x).
9101 
9102 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9103 @*/
9104 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9105 {
9106   PetscFunctionBegin;
9107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9108   PetscValidType(mat, 1);
9109   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9110   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9111   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9112 
9113   MatCheckPreallocated(mat, 1);
9114   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9115   PetscUseTypeMethod(mat, solves, b, x);
9116   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9117   PetscFunctionReturn(PETSC_SUCCESS);
9118 }
9119 
9120 /*@
9121    MatIsSymmetric - Test whether a matrix is symmetric
9122 
9123    Collective
9124 
9125    Input Parameters:
9126 +  A - the matrix to test
9127 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9128 
9129    Output Parameter:
9130 .  flg - the result
9131 
9132    Level: intermediate
9133 
9134    Notes:
9135     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9136 
9137     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9138 
9139     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9140     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9141 
9142 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9143           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9144 @*/
9145 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9146 {
9147   PetscFunctionBegin;
9148   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9149   PetscValidBoolPointer(flg, 3);
9150 
9151   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9152   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9153   else {
9154     PetscUseTypeMethod(A, issymmetric, tol, flg);
9155     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9156   }
9157   PetscFunctionReturn(PETSC_SUCCESS);
9158 }
9159 
9160 /*@
9161    MatIsHermitian - Test whether a matrix is Hermitian
9162 
9163    Collective
9164 
9165    Input Parameters:
9166 +  A - the matrix to test
9167 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9168 
9169    Output Parameter:
9170 .  flg - the result
9171 
9172    Level: intermediate
9173 
9174    Notes:
9175     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9176 
9177     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9178 
9179     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9180     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9181 
9182 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9183           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9184 @*/
9185 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9186 {
9187   PetscFunctionBegin;
9188   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9189   PetscValidBoolPointer(flg, 3);
9190 
9191   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9192   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9193   else {
9194     PetscUseTypeMethod(A, ishermitian, tol, flg);
9195     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9196   }
9197   PetscFunctionReturn(PETSC_SUCCESS);
9198 }
9199 
9200 /*@
9201    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9202 
9203    Not Collective
9204 
9205    Input Parameter:
9206 .  A - the matrix to check
9207 
9208    Output Parameters:
9209 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9210 -  flg - the result (only valid if set is `PETSC_TRUE`)
9211 
9212    Level: advanced
9213 
9214    Notes:
9215    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9216    if you want it explicitly checked
9217 
9218     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9219     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9220 
9221 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9222 @*/
9223 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9224 {
9225   PetscFunctionBegin;
9226   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9227   PetscValidBoolPointer(set, 2);
9228   PetscValidBoolPointer(flg, 3);
9229   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9230     *set = PETSC_TRUE;
9231     *flg = PetscBool3ToBool(A->symmetric);
9232   } else {
9233     *set = PETSC_FALSE;
9234   }
9235   PetscFunctionReturn(PETSC_SUCCESS);
9236 }
9237 
9238 /*@
9239    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9240 
9241    Not Collective
9242 
9243    Input Parameter:
9244 .  A - the matrix to check
9245 
9246    Output Parameters:
9247 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9248 -  flg - the result (only valid if set is `PETSC_TRUE`)
9249 
9250    Level: advanced
9251 
9252    Notes:
9253    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9254 
9255    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9256    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9257 
9258 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9259 @*/
9260 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9261 {
9262   PetscFunctionBegin;
9263   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9264   PetscValidBoolPointer(set, 2);
9265   PetscValidBoolPointer(flg, 3);
9266   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9267     *set = PETSC_TRUE;
9268     *flg = PetscBool3ToBool(A->spd);
9269   } else {
9270     *set = PETSC_FALSE;
9271   }
9272   PetscFunctionReturn(PETSC_SUCCESS);
9273 }
9274 
9275 /*@
9276    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9277 
9278    Not Collective
9279 
9280    Input Parameter:
9281 .  A - the matrix to check
9282 
9283    Output Parameters:
9284 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9285 -  flg - the result (only valid if set is `PETSC_TRUE`)
9286 
9287    Level: advanced
9288 
9289    Notes:
9290    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9291    if you want it explicitly checked
9292 
9293    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9294    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9295 
9296 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9297 @*/
9298 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9299 {
9300   PetscFunctionBegin;
9301   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9302   PetscValidBoolPointer(set, 2);
9303   PetscValidBoolPointer(flg, 3);
9304   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9305     *set = PETSC_TRUE;
9306     *flg = PetscBool3ToBool(A->hermitian);
9307   } else {
9308     *set = PETSC_FALSE;
9309   }
9310   PetscFunctionReturn(PETSC_SUCCESS);
9311 }
9312 
9313 /*@
9314    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9315 
9316    Collective
9317 
9318    Input Parameter:
9319 .  A - the matrix to test
9320 
9321    Output Parameter:
9322 .  flg - the result
9323 
9324    Level: intermediate
9325 
9326    Notes:
9327    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9328 
9329    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
9330    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9331 
9332 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9333 @*/
9334 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9335 {
9336   PetscFunctionBegin;
9337   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9338   PetscValidBoolPointer(flg, 2);
9339   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9340     *flg = PetscBool3ToBool(A->structurally_symmetric);
9341   } else {
9342     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9343     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9344   }
9345   PetscFunctionReturn(PETSC_SUCCESS);
9346 }
9347 
9348 /*@
9349    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9350 
9351    Not Collective
9352 
9353    Input Parameter:
9354 .  A - the matrix to check
9355 
9356    Output Parameters:
9357 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9358 -  flg - the result (only valid if set is PETSC_TRUE)
9359 
9360    Level: advanced
9361 
9362    Notes:
9363    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
9364    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9365 
9366    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9367 
9368 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9369 @*/
9370 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9371 {
9372   PetscFunctionBegin;
9373   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9374   PetscValidBoolPointer(set, 2);
9375   PetscValidBoolPointer(flg, 3);
9376   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9377     *set = PETSC_TRUE;
9378     *flg = PetscBool3ToBool(A->structurally_symmetric);
9379   } else {
9380     *set = PETSC_FALSE;
9381   }
9382   PetscFunctionReturn(PETSC_SUCCESS);
9383 }
9384 
9385 /*@
9386    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9387        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9388 
9389     Not Collective
9390 
9391    Input Parameter:
9392 .   mat - the matrix
9393 
9394    Output Parameters:
9395 +   nstash   - the size of the stash
9396 .   reallocs - the number of additional mallocs incurred.
9397 .   bnstash   - the size of the block stash
9398 -   breallocs - the number of additional mallocs incurred.in the block stash
9399 
9400    Level: advanced
9401 
9402 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9403 @*/
9404 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9405 {
9406   PetscFunctionBegin;
9407   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9408   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9409   PetscFunctionReturn(PETSC_SUCCESS);
9410 }
9411 
9412 /*@C
9413    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9414    parallel layout, `PetscLayout` for rows and columns
9415 
9416    Collective
9417 
9418    Input Parameter:
9419 .  mat - the matrix
9420 
9421    Output Parameters:
9422 +   right - (optional) vector that the matrix can be multiplied against
9423 -   left - (optional) vector that the matrix vector product can be stored in
9424 
9425   Level: advanced
9426 
9427    Notes:
9428     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()`.
9429 
9430     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9431 
9432 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9433 @*/
9434 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9435 {
9436   PetscFunctionBegin;
9437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9438   PetscValidType(mat, 1);
9439   if (mat->ops->getvecs) {
9440     PetscUseTypeMethod(mat, getvecs, right, left);
9441   } else {
9442     PetscInt rbs, cbs;
9443     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9444     if (right) {
9445       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9446       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9447       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9448       PetscCall(VecSetBlockSize(*right, cbs));
9449       PetscCall(VecSetType(*right, mat->defaultvectype));
9450 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9451       if (mat->boundtocpu && mat->bindingpropagates) {
9452         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9453         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9454       }
9455 #endif
9456       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9457     }
9458     if (left) {
9459       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9460       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9461       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9462       PetscCall(VecSetBlockSize(*left, rbs));
9463       PetscCall(VecSetType(*left, mat->defaultvectype));
9464 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9465       if (mat->boundtocpu && mat->bindingpropagates) {
9466         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9467         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9468       }
9469 #endif
9470       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9471     }
9472   }
9473   PetscFunctionReturn(PETSC_SUCCESS);
9474 }
9475 
9476 /*@C
9477    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9478      with default values.
9479 
9480    Not Collective
9481 
9482    Input Parameter:
9483 .    info - the `MatFactorInfo` data structure
9484 
9485    Level: developer
9486 
9487    Notes:
9488     The solvers are generally used through the `KSP` and `PC` objects, for example
9489           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9490 
9491     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9492 
9493    Developer Note:
9494    The Fortran interface is not autogenerated as the
9495    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9496 
9497 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9498 @*/
9499 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9500 {
9501   PetscFunctionBegin;
9502   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9503   PetscFunctionReturn(PETSC_SUCCESS);
9504 }
9505 
9506 /*@
9507    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9508 
9509    Collective
9510 
9511    Input Parameters:
9512 +  mat - the factored matrix
9513 -  is - the index set defining the Schur indices (0-based)
9514 
9515    Level: advanced
9516 
9517    Notes:
9518     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9519 
9520    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9521 
9522    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9523 
9524 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9525           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9526 @*/
9527 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9528 {
9529   PetscErrorCode (*f)(Mat, IS);
9530 
9531   PetscFunctionBegin;
9532   PetscValidType(mat, 1);
9533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9534   PetscValidType(is, 2);
9535   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9536   PetscCheckSameComm(mat, 1, is, 2);
9537   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9538   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9539   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9540   PetscCall(MatDestroy(&mat->schur));
9541   PetscCall((*f)(mat, is));
9542   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9543   PetscFunctionReturn(PETSC_SUCCESS);
9544 }
9545 
9546 /*@
9547   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9548 
9549    Logically Collective
9550 
9551    Input Parameters:
9552 +  F - the factored matrix obtained by calling `MatGetFactor()`
9553 .  S - location where to return the Schur complement, can be `NULL`
9554 -  status - the status of the Schur complement matrix, can be `NULL`
9555 
9556    Level: advanced
9557 
9558    Notes:
9559    You must call `MatFactorSetSchurIS()` before calling this routine.
9560 
9561    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9562 
9563    The routine provides a copy of the Schur matrix stored within the solver data structures.
9564    The caller must destroy the object when it is no longer needed.
9565    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9566 
9567    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)
9568 
9569    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9570 
9571    Developer Note:
9572     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9573    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9574 
9575 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9576 @*/
9577 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9578 {
9579   PetscFunctionBegin;
9580   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9581   if (S) PetscValidPointer(S, 2);
9582   if (status) PetscValidPointer(status, 3);
9583   if (S) {
9584     PetscErrorCode (*f)(Mat, Mat *);
9585 
9586     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9587     if (f) {
9588       PetscCall((*f)(F, S));
9589     } else {
9590       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9591     }
9592   }
9593   if (status) *status = F->schur_status;
9594   PetscFunctionReturn(PETSC_SUCCESS);
9595 }
9596 
9597 /*@
9598   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9599 
9600    Logically Collective
9601 
9602    Input Parameters:
9603 +  F - the factored matrix obtained by calling `MatGetFactor()`
9604 .  *S - location where to return the Schur complement, can be `NULL`
9605 -  status - the status of the Schur complement matrix, can be `NULL`
9606 
9607    Level: advanced
9608 
9609    Notes:
9610    You must call `MatFactorSetSchurIS()` before calling this routine.
9611 
9612    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9613 
9614    The routine returns a the Schur Complement stored within the data structures of the solver.
9615 
9616    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9617 
9618    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9619 
9620    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9621 
9622    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9623 
9624 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9625 @*/
9626 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9627 {
9628   PetscFunctionBegin;
9629   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9630   if (S) PetscValidPointer(S, 2);
9631   if (status) PetscValidPointer(status, 3);
9632   if (S) *S = F->schur;
9633   if (status) *status = F->schur_status;
9634   PetscFunctionReturn(PETSC_SUCCESS);
9635 }
9636 
9637 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9638 {
9639   Mat S = F->schur;
9640 
9641   PetscFunctionBegin;
9642   switch (F->schur_status) {
9643   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9644   case MAT_FACTOR_SCHUR_INVERTED:
9645     if (S) {
9646       S->ops->solve             = NULL;
9647       S->ops->matsolve          = NULL;
9648       S->ops->solvetranspose    = NULL;
9649       S->ops->matsolvetranspose = NULL;
9650       S->ops->solveadd          = NULL;
9651       S->ops->solvetransposeadd = NULL;
9652       S->factortype             = MAT_FACTOR_NONE;
9653       PetscCall(PetscFree(S->solvertype));
9654     }
9655   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9656     break;
9657   default:
9658     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9659   }
9660   PetscFunctionReturn(PETSC_SUCCESS);
9661 }
9662 
9663 /*@
9664   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9665 
9666    Logically Collective
9667 
9668    Input Parameters:
9669 +  F - the factored matrix obtained by calling `MatGetFactor()`
9670 .  *S - location where the Schur complement is stored
9671 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9672 
9673    Level: advanced
9674 
9675 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9676 @*/
9677 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9678 {
9679   PetscFunctionBegin;
9680   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9681   if (S) {
9682     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9683     *S = NULL;
9684   }
9685   F->schur_status = status;
9686   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9687   PetscFunctionReturn(PETSC_SUCCESS);
9688 }
9689 
9690 /*@
9691   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9692 
9693    Logically Collective
9694 
9695    Input Parameters:
9696 +  F - the factored matrix obtained by calling `MatGetFactor()`
9697 .  rhs - location where the right hand side of the Schur complement system is stored
9698 -  sol - location where the solution of the Schur complement system has to be returned
9699 
9700    Level: advanced
9701 
9702    Notes:
9703    The sizes of the vectors should match the size of the Schur complement
9704 
9705    Must be called after `MatFactorSetSchurIS()`
9706 
9707 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9708 @*/
9709 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9710 {
9711   PetscFunctionBegin;
9712   PetscValidType(F, 1);
9713   PetscValidType(rhs, 2);
9714   PetscValidType(sol, 3);
9715   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9716   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9717   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9718   PetscCheckSameComm(F, 1, rhs, 2);
9719   PetscCheckSameComm(F, 1, sol, 3);
9720   PetscCall(MatFactorFactorizeSchurComplement(F));
9721   switch (F->schur_status) {
9722   case MAT_FACTOR_SCHUR_FACTORED:
9723     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9724     break;
9725   case MAT_FACTOR_SCHUR_INVERTED:
9726     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9727     break;
9728   default:
9729     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9730   }
9731   PetscFunctionReturn(PETSC_SUCCESS);
9732 }
9733 
9734 /*@
9735   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9736 
9737    Logically Collective
9738 
9739    Input Parameters:
9740 +  F - the factored matrix obtained by calling `MatGetFactor()`
9741 .  rhs - location where the right hand side of the Schur complement system is stored
9742 -  sol - location where the solution of the Schur complement system has to be returned
9743 
9744    Level: advanced
9745 
9746    Notes:
9747    The sizes of the vectors should match the size of the Schur complement
9748 
9749    Must be called after `MatFactorSetSchurIS()`
9750 
9751 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9752 @*/
9753 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9754 {
9755   PetscFunctionBegin;
9756   PetscValidType(F, 1);
9757   PetscValidType(rhs, 2);
9758   PetscValidType(sol, 3);
9759   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9760   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9761   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9762   PetscCheckSameComm(F, 1, rhs, 2);
9763   PetscCheckSameComm(F, 1, sol, 3);
9764   PetscCall(MatFactorFactorizeSchurComplement(F));
9765   switch (F->schur_status) {
9766   case MAT_FACTOR_SCHUR_FACTORED:
9767     PetscCall(MatSolve(F->schur, rhs, sol));
9768     break;
9769   case MAT_FACTOR_SCHUR_INVERTED:
9770     PetscCall(MatMult(F->schur, rhs, sol));
9771     break;
9772   default:
9773     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9774   }
9775   PetscFunctionReturn(PETSC_SUCCESS);
9776 }
9777 
9778 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9779 #if PetscDefined(HAVE_CUDA)
9780 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9781 #endif
9782 
9783 /* Schur status updated in the interface */
9784 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9785 {
9786   Mat S = F->schur;
9787 
9788   PetscFunctionBegin;
9789   if (S) {
9790     PetscMPIInt size;
9791     PetscBool   isdense, isdensecuda;
9792 
9793     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9794     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9795     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9796     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9797     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9798     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9799     if (isdense) {
9800       PetscCall(MatSeqDenseInvertFactors_Private(S));
9801     } else if (isdensecuda) {
9802 #if defined(PETSC_HAVE_CUDA)
9803       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9804 #endif
9805     }
9806     // HIP??????????????
9807     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9808   }
9809   PetscFunctionReturn(PETSC_SUCCESS);
9810 }
9811 
9812 /*@
9813   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9814 
9815    Logically Collective
9816 
9817    Input Parameter:
9818 .  F - the factored matrix obtained by calling `MatGetFactor()`
9819 
9820    Level: advanced
9821 
9822    Notes:
9823     Must be called after `MatFactorSetSchurIS()`.
9824 
9825    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9826 
9827 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9828 @*/
9829 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9830 {
9831   PetscFunctionBegin;
9832   PetscValidType(F, 1);
9833   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9834   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9835   PetscCall(MatFactorFactorizeSchurComplement(F));
9836   PetscCall(MatFactorInvertSchurComplement_Private(F));
9837   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9838   PetscFunctionReturn(PETSC_SUCCESS);
9839 }
9840 
9841 /*@
9842   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9843 
9844    Logically Collective
9845 
9846    Input Parameter:
9847 .  F - the factored matrix obtained by calling `MatGetFactor()`
9848 
9849    Level: advanced
9850 
9851    Note:
9852     Must be called after `MatFactorSetSchurIS()`
9853 
9854 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9855 @*/
9856 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9857 {
9858   MatFactorInfo info;
9859 
9860   PetscFunctionBegin;
9861   PetscValidType(F, 1);
9862   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9863   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9864   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9865   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9866   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9867     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9868   } else {
9869     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9870   }
9871   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9872   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9873   PetscFunctionReturn(PETSC_SUCCESS);
9874 }
9875 
9876 /*@
9877    MatPtAP - Creates the matrix product C = P^T * A * P
9878 
9879    Neighbor-wise Collective
9880 
9881    Input Parameters:
9882 +  A - the matrix
9883 .  P - the projection matrix
9884 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9885 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9886           if the result is a dense matrix this is irrelevant
9887 
9888    Output Parameter:
9889 .  C - the product matrix
9890 
9891    Level: intermediate
9892 
9893    Notes:
9894    C will be created and must be destroyed by the user with `MatDestroy()`.
9895 
9896    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9897 
9898    Developer Note:
9899    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9900 
9901 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9902 @*/
9903 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9904 {
9905   PetscFunctionBegin;
9906   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9907   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9908 
9909   if (scall == MAT_INITIAL_MATRIX) {
9910     PetscCall(MatProductCreate(A, P, NULL, C));
9911     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9912     PetscCall(MatProductSetAlgorithm(*C, "default"));
9913     PetscCall(MatProductSetFill(*C, fill));
9914 
9915     (*C)->product->api_user = PETSC_TRUE;
9916     PetscCall(MatProductSetFromOptions(*C));
9917     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);
9918     PetscCall(MatProductSymbolic(*C));
9919   } else { /* scall == MAT_REUSE_MATRIX */
9920     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9921   }
9922 
9923   PetscCall(MatProductNumeric(*C));
9924   (*C)->symmetric = A->symmetric;
9925   (*C)->spd       = A->spd;
9926   PetscFunctionReturn(PETSC_SUCCESS);
9927 }
9928 
9929 /*@
9930    MatRARt - Creates the matrix product C = R * A * R^T
9931 
9932    Neighbor-wise Collective
9933 
9934    Input Parameters:
9935 +  A - the matrix
9936 .  R - the projection matrix
9937 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9938 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9939           if the result is a dense matrix this is irrelevant
9940 
9941    Output Parameter:
9942 .  C - the product matrix
9943 
9944    Level: intermediate
9945 
9946    Notes:
9947    C will be created and must be destroyed by the user with `MatDestroy()`.
9948 
9949    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9950 
9951    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9952    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9953    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9954    We recommend using MatPtAP().
9955 
9956 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9957 @*/
9958 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9959 {
9960   PetscFunctionBegin;
9961   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9962   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9963 
9964   if (scall == MAT_INITIAL_MATRIX) {
9965     PetscCall(MatProductCreate(A, R, NULL, C));
9966     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9967     PetscCall(MatProductSetAlgorithm(*C, "default"));
9968     PetscCall(MatProductSetFill(*C, fill));
9969 
9970     (*C)->product->api_user = PETSC_TRUE;
9971     PetscCall(MatProductSetFromOptions(*C));
9972     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);
9973     PetscCall(MatProductSymbolic(*C));
9974   } else { /* scall == MAT_REUSE_MATRIX */
9975     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9976   }
9977 
9978   PetscCall(MatProductNumeric(*C));
9979   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9980   PetscFunctionReturn(PETSC_SUCCESS);
9981 }
9982 
9983 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9984 {
9985   PetscFunctionBegin;
9986   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9987 
9988   if (scall == MAT_INITIAL_MATRIX) {
9989     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9990     PetscCall(MatProductCreate(A, B, NULL, C));
9991     PetscCall(MatProductSetType(*C, ptype));
9992     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9993     PetscCall(MatProductSetFill(*C, fill));
9994 
9995     (*C)->product->api_user = PETSC_TRUE;
9996     PetscCall(MatProductSetFromOptions(*C));
9997     PetscCall(MatProductSymbolic(*C));
9998   } else { /* scall == MAT_REUSE_MATRIX */
9999     Mat_Product *product = (*C)->product;
10000     PetscBool    isdense;
10001 
10002     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10003     if (isdense && product && product->type != ptype) {
10004       PetscCall(MatProductClear(*C));
10005       product = NULL;
10006     }
10007     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10008     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10009       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10010       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10011       product           = (*C)->product;
10012       product->fill     = fill;
10013       product->api_user = PETSC_TRUE;
10014       product->clear    = PETSC_TRUE;
10015 
10016       PetscCall(MatProductSetType(*C, ptype));
10017       PetscCall(MatProductSetFromOptions(*C));
10018       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);
10019       PetscCall(MatProductSymbolic(*C));
10020     } else { /* user may change input matrices A or B when REUSE */
10021       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10022     }
10023   }
10024   PetscCall(MatProductNumeric(*C));
10025   PetscFunctionReturn(PETSC_SUCCESS);
10026 }
10027 
10028 /*@
10029    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10030 
10031    Neighbor-wise Collective
10032 
10033    Input Parameters:
10034 +  A - the left matrix
10035 .  B - the right matrix
10036 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10037 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10038           if the result is a dense matrix this is irrelevant
10039 
10040    Output Parameter:
10041 .  C - the product matrix
10042 
10043    Notes:
10044    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10045 
10046    `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
10047    call to this function with `MAT_INITIAL_MATRIX`.
10048 
10049    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10050 
10051    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`,
10052    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10053 
10054    Example of Usage:
10055 .vb
10056      MatProductCreate(A,B,NULL,&C);
10057      MatProductSetType(C,MATPRODUCT_AB);
10058      MatProductSymbolic(C);
10059      MatProductNumeric(C); // compute C=A * B
10060      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10061      MatProductNumeric(C);
10062      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10063      MatProductNumeric(C);
10064 .ve
10065 
10066    Level: intermediate
10067 
10068 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10069 @*/
10070 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10071 {
10072   PetscFunctionBegin;
10073   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10074   PetscFunctionReturn(PETSC_SUCCESS);
10075 }
10076 
10077 /*@
10078    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10079 
10080    Neighbor-wise Collective
10081 
10082    Input Parameters:
10083 +  A - the left matrix
10084 .  B - the right matrix
10085 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10086 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10087 
10088    Output Parameter:
10089 .  C - the product matrix
10090 
10091    Level: intermediate
10092 
10093    Notes:
10094    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10095 
10096    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10097 
10098    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10099    actually needed.
10100 
10101    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10102    and for pairs of `MATMPIDENSE` matrices.
10103 
10104    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10105 
10106    Options Database Keys:
10107 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10108               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10109               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10110 
10111 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10112 @*/
10113 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10114 {
10115   PetscFunctionBegin;
10116   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10117   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10118   PetscFunctionReturn(PETSC_SUCCESS);
10119 }
10120 
10121 /*@
10122    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10123 
10124    Neighbor-wise Collective
10125 
10126    Input Parameters:
10127 +  A - the left matrix
10128 .  B - the right matrix
10129 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10130 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10131 
10132    Output Parameter:
10133 .  C - the product matrix
10134 
10135    Level: intermediate
10136 
10137    Notes:
10138    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10139 
10140    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10141 
10142    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10143 
10144    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10145    actually needed.
10146 
10147    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10148    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10149 
10150 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10151 @*/
10152 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10153 {
10154   PetscFunctionBegin;
10155   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10156   PetscFunctionReturn(PETSC_SUCCESS);
10157 }
10158 
10159 /*@
10160    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10161 
10162    Neighbor-wise Collective
10163 
10164    Input Parameters:
10165 +  A - the left matrix
10166 .  B - the middle matrix
10167 .  C - the right matrix
10168 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10169 -  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
10170           if the result is a dense matrix this is irrelevant
10171 
10172    Output Parameter:
10173 .  D - the product matrix
10174 
10175    Level: intermediate
10176 
10177    Notes:
10178    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10179 
10180    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10181 
10182    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10183 
10184    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10185    actually needed.
10186 
10187    If you have many matrices with the same non-zero structure to multiply, you
10188    should use `MAT_REUSE_MATRIX` in all calls but the first
10189 
10190 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10191 @*/
10192 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10193 {
10194   PetscFunctionBegin;
10195   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10196   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10197 
10198   if (scall == MAT_INITIAL_MATRIX) {
10199     PetscCall(MatProductCreate(A, B, C, D));
10200     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10201     PetscCall(MatProductSetAlgorithm(*D, "default"));
10202     PetscCall(MatProductSetFill(*D, fill));
10203 
10204     (*D)->product->api_user = PETSC_TRUE;
10205     PetscCall(MatProductSetFromOptions(*D));
10206     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,
10207                ((PetscObject)C)->type_name);
10208     PetscCall(MatProductSymbolic(*D));
10209   } else { /* user may change input matrices when REUSE */
10210     PetscCall(MatProductReplaceMats(A, B, C, *D));
10211   }
10212   PetscCall(MatProductNumeric(*D));
10213   PetscFunctionReturn(PETSC_SUCCESS);
10214 }
10215 
10216 /*@
10217    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10218 
10219    Collective
10220 
10221    Input Parameters:
10222 +  mat - the matrix
10223 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10224 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10225 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10226 
10227    Output Parameter:
10228 .  matredundant - redundant matrix
10229 
10230    Level: advanced
10231 
10232    Notes:
10233    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10234    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10235 
10236    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10237    calling it.
10238 
10239    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10240 
10241 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10242 @*/
10243 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10244 {
10245   MPI_Comm       comm;
10246   PetscMPIInt    size;
10247   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10248   Mat_Redundant *redund     = NULL;
10249   PetscSubcomm   psubcomm   = NULL;
10250   MPI_Comm       subcomm_in = subcomm;
10251   Mat           *matseq;
10252   IS             isrow, iscol;
10253   PetscBool      newsubcomm = PETSC_FALSE;
10254 
10255   PetscFunctionBegin;
10256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10257   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10258     PetscValidPointer(*matredundant, 5);
10259     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10260   }
10261 
10262   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10263   if (size == 1 || nsubcomm == 1) {
10264     if (reuse == MAT_INITIAL_MATRIX) {
10265       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10266     } else {
10267       PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10268       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10269     }
10270     PetscFunctionReturn(PETSC_SUCCESS);
10271   }
10272 
10273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10275   MatCheckPreallocated(mat, 1);
10276 
10277   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10278   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10279     /* create psubcomm, then get subcomm */
10280     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10281     PetscCallMPI(MPI_Comm_size(comm, &size));
10282     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10283 
10284     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10285     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10286     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10287     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10288     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10289     newsubcomm = PETSC_TRUE;
10290     PetscCall(PetscSubcommDestroy(&psubcomm));
10291   }
10292 
10293   /* get isrow, iscol and a local sequential matrix matseq[0] */
10294   if (reuse == MAT_INITIAL_MATRIX) {
10295     mloc_sub = PETSC_DECIDE;
10296     nloc_sub = PETSC_DECIDE;
10297     if (bs < 1) {
10298       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10299       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10300     } else {
10301       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10302       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10303     }
10304     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10305     rstart = rend - mloc_sub;
10306     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10307     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10308   } else { /* reuse == MAT_REUSE_MATRIX */
10309     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");
10310     /* retrieve subcomm */
10311     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10312     redund = (*matredundant)->redundant;
10313     isrow  = redund->isrow;
10314     iscol  = redund->iscol;
10315     matseq = redund->matseq;
10316   }
10317   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10318 
10319   /* get matredundant over subcomm */
10320   if (reuse == MAT_INITIAL_MATRIX) {
10321     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10322 
10323     /* create a supporting struct and attach it to C for reuse */
10324     PetscCall(PetscNew(&redund));
10325     (*matredundant)->redundant = redund;
10326     redund->isrow              = isrow;
10327     redund->iscol              = iscol;
10328     redund->matseq             = matseq;
10329     if (newsubcomm) {
10330       redund->subcomm = subcomm;
10331     } else {
10332       redund->subcomm = MPI_COMM_NULL;
10333     }
10334   } else {
10335     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10336   }
10337 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10338   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10339     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10340     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10341   }
10342 #endif
10343   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10344   PetscFunctionReturn(PETSC_SUCCESS);
10345 }
10346 
10347 /*@C
10348    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10349    a given `Mat`. Each submatrix can span multiple procs.
10350 
10351    Collective
10352 
10353    Input Parameters:
10354 +  mat - the matrix
10355 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10356 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10357 
10358    Output Parameter:
10359 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10360 
10361   Level: advanced
10362 
10363   Notes:
10364   The submatrix partition across processors is dictated by `subComm` a
10365   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10366   is not restricted to be grouped with consecutive original ranks.
10367 
10368   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10369   map directly to the layout of the original matrix [wrt the local
10370   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10371   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10372   the `subMat`. However the offDiagMat looses some columns - and this is
10373   reconstructed with `MatSetValues()`
10374 
10375   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10376 
10377 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10378 @*/
10379 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10380 {
10381   PetscMPIInt commsize, subCommSize;
10382 
10383   PetscFunctionBegin;
10384   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10385   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10386   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10387 
10388   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");
10389   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10390   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10391   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10392   PetscFunctionReturn(PETSC_SUCCESS);
10393 }
10394 
10395 /*@
10396    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10397 
10398    Not Collective
10399 
10400    Input Parameters:
10401 +  mat - matrix to extract local submatrix from
10402 .  isrow - local row indices for submatrix
10403 -  iscol - local column indices for submatrix
10404 
10405    Output Parameter:
10406 .  submat - the submatrix
10407 
10408    Level: intermediate
10409 
10410    Notes:
10411    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10412 
10413    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10414    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10415 
10416    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10417    `MatSetValuesBlockedLocal()` will also be implemented.
10418 
10419    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10420    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10421 
10422 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10423 @*/
10424 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10425 {
10426   PetscFunctionBegin;
10427   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10428   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10429   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10430   PetscCheckSameComm(isrow, 2, iscol, 3);
10431   PetscValidPointer(submat, 4);
10432   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10433 
10434   if (mat->ops->getlocalsubmatrix) {
10435     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10436   } else {
10437     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10438   }
10439   PetscFunctionReturn(PETSC_SUCCESS);
10440 }
10441 
10442 /*@
10443    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10444 
10445    Not Collective
10446 
10447    Input Parameters:
10448 +  mat - matrix to extract local submatrix from
10449 .  isrow - local row indices for submatrix
10450 .  iscol - local column indices for submatrix
10451 -  submat - the submatrix
10452 
10453    Level: intermediate
10454 
10455 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10456 @*/
10457 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10458 {
10459   PetscFunctionBegin;
10460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10461   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10462   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10463   PetscCheckSameComm(isrow, 2, iscol, 3);
10464   PetscValidPointer(submat, 4);
10465   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10466 
10467   if (mat->ops->restorelocalsubmatrix) {
10468     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10469   } else {
10470     PetscCall(MatDestroy(submat));
10471   }
10472   *submat = NULL;
10473   PetscFunctionReturn(PETSC_SUCCESS);
10474 }
10475 
10476 /*@
10477    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10478 
10479    Collective
10480 
10481    Input Parameter:
10482 .  mat - the matrix
10483 
10484    Output Parameter:
10485 .  is - if any rows have zero diagonals this contains the list of them
10486 
10487    Level: developer
10488 
10489 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10490 @*/
10491 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10492 {
10493   PetscFunctionBegin;
10494   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10495   PetscValidType(mat, 1);
10496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10498 
10499   if (!mat->ops->findzerodiagonals) {
10500     Vec                diag;
10501     const PetscScalar *a;
10502     PetscInt          *rows;
10503     PetscInt           rStart, rEnd, r, nrow = 0;
10504 
10505     PetscCall(MatCreateVecs(mat, &diag, NULL));
10506     PetscCall(MatGetDiagonal(mat, diag));
10507     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10508     PetscCall(VecGetArrayRead(diag, &a));
10509     for (r = 0; r < rEnd - rStart; ++r)
10510       if (a[r] == 0.0) ++nrow;
10511     PetscCall(PetscMalloc1(nrow, &rows));
10512     nrow = 0;
10513     for (r = 0; r < rEnd - rStart; ++r)
10514       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10515     PetscCall(VecRestoreArrayRead(diag, &a));
10516     PetscCall(VecDestroy(&diag));
10517     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10518   } else {
10519     PetscUseTypeMethod(mat, findzerodiagonals, is);
10520   }
10521   PetscFunctionReturn(PETSC_SUCCESS);
10522 }
10523 
10524 /*@
10525    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10526 
10527    Collective
10528 
10529    Input Parameter:
10530 .  mat - the matrix
10531 
10532    Output Parameter:
10533 .  is - contains the list of rows with off block diagonal entries
10534 
10535    Level: developer
10536 
10537 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10538 @*/
10539 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10540 {
10541   PetscFunctionBegin;
10542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10543   PetscValidType(mat, 1);
10544   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10545   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10546 
10547   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10548   PetscFunctionReturn(PETSC_SUCCESS);
10549 }
10550 
10551 /*@C
10552   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10553 
10554   Collective; No Fortran Support
10555 
10556   Input Parameter:
10557 . mat - the matrix
10558 
10559   Output Parameter:
10560 . values - the block inverses in column major order (FORTRAN-like)
10561 
10562   Level: advanced
10563 
10564    Notes:
10565    The size of the blocks is determined by the block size of the matrix.
10566 
10567    The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10568 
10569    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10570 
10571 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10572 @*/
10573 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10574 {
10575   PetscFunctionBegin;
10576   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10577   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10578   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10579   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10580   PetscFunctionReturn(PETSC_SUCCESS);
10581 }
10582 
10583 /*@C
10584   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10585 
10586   Collective; No Fortran Support
10587 
10588   Input Parameters:
10589 + mat - the matrix
10590 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10591 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10592 
10593   Output Parameter:
10594 . values - the block inverses in column major order (FORTRAN-like)
10595 
10596   Level: advanced
10597 
10598   Notes:
10599   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10600 
10601   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10602 
10603 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10604 @*/
10605 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10606 {
10607   PetscFunctionBegin;
10608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10609   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10610   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10611   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10612   PetscFunctionReturn(PETSC_SUCCESS);
10613 }
10614 
10615 /*@
10616   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10617 
10618   Collective
10619 
10620   Input Parameters:
10621 + A - the matrix
10622 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10623 
10624   Level: advanced
10625 
10626   Note:
10627   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10628 
10629 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10630 @*/
10631 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10632 {
10633   const PetscScalar *vals;
10634   PetscInt          *dnnz;
10635   PetscInt           m, rstart, rend, bs, i, j;
10636 
10637   PetscFunctionBegin;
10638   PetscCall(MatInvertBlockDiagonal(A, &vals));
10639   PetscCall(MatGetBlockSize(A, &bs));
10640   PetscCall(MatGetLocalSize(A, &m, NULL));
10641   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10642   PetscCall(PetscMalloc1(m / bs, &dnnz));
10643   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10644   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10645   PetscCall(PetscFree(dnnz));
10646   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10647   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10648   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10649   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10650   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10651   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10652   PetscFunctionReturn(PETSC_SUCCESS);
10653 }
10654 
10655 /*@C
10656     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10657     via `MatTransposeColoringCreate()`.
10658 
10659     Collective
10660 
10661     Input Parameter:
10662 .   c - coloring context
10663 
10664     Level: intermediate
10665 
10666 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10667 @*/
10668 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10669 {
10670   MatTransposeColoring matcolor = *c;
10671 
10672   PetscFunctionBegin;
10673   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10674   if (--((PetscObject)matcolor)->refct > 0) {
10675     matcolor = NULL;
10676     PetscFunctionReturn(PETSC_SUCCESS);
10677   }
10678 
10679   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10680   PetscCall(PetscFree(matcolor->rows));
10681   PetscCall(PetscFree(matcolor->den2sp));
10682   PetscCall(PetscFree(matcolor->colorforcol));
10683   PetscCall(PetscFree(matcolor->columns));
10684   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10685   PetscCall(PetscHeaderDestroy(c));
10686   PetscFunctionReturn(PETSC_SUCCESS);
10687 }
10688 
10689 /*@C
10690     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10691     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10692     `MatTransposeColoring` to sparse B.
10693 
10694     Collective
10695 
10696     Input Parameters:
10697 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10698 -   B - sparse matrix
10699 
10700     Output Parameter:
10701 .   Btdense - dense matrix B^T
10702 
10703     Level: developer
10704 
10705     Note:
10706     These are used internally for some implementations of `MatRARt()`
10707 
10708 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10709 @*/
10710 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10711 {
10712   PetscFunctionBegin;
10713   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10714   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10715   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10716 
10717   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10718   PetscFunctionReturn(PETSC_SUCCESS);
10719 }
10720 
10721 /*@C
10722     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10723     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10724     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10725     `Csp` from `Cden`.
10726 
10727     Collective
10728 
10729     Input Parameters:
10730 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10731 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10732 
10733     Output Parameter:
10734 .   Csp - sparse matrix
10735 
10736     Level: developer
10737 
10738     Note:
10739     These are used internally for some implementations of `MatRARt()`
10740 
10741 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10742 @*/
10743 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10744 {
10745   PetscFunctionBegin;
10746   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10747   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10748   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10749 
10750   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10751   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10752   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10753   PetscFunctionReturn(PETSC_SUCCESS);
10754 }
10755 
10756 /*@C
10757    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10758 
10759    Collective
10760 
10761    Input Parameters:
10762 +  mat - the matrix product C
10763 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10764 
10765     Output Parameter:
10766 .   color - the new coloring context
10767 
10768     Level: intermediate
10769 
10770 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10771           `MatTransColoringApplyDenToSp()`
10772 @*/
10773 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10774 {
10775   MatTransposeColoring c;
10776   MPI_Comm             comm;
10777 
10778   PetscFunctionBegin;
10779   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10780   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10781   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10782 
10783   c->ctype = iscoloring->ctype;
10784   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10785 
10786   *color = c;
10787   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10788   PetscFunctionReturn(PETSC_SUCCESS);
10789 }
10790 
10791 /*@
10792       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10793         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10794         same, otherwise it will be larger
10795 
10796      Not Collective
10797 
10798   Input Parameter:
10799 .    A  - the matrix
10800 
10801   Output Parameter:
10802 .    state - the current state
10803 
10804   Level: intermediate
10805 
10806   Notes:
10807     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10808          different matrices
10809 
10810     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10811 
10812     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10813 
10814 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10815 @*/
10816 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10817 {
10818   PetscFunctionBegin;
10819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10820   *state = mat->nonzerostate;
10821   PetscFunctionReturn(PETSC_SUCCESS);
10822 }
10823 
10824 /*@
10825       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10826                  matrices from each processor
10827 
10828     Collective
10829 
10830    Input Parameters:
10831 +    comm - the communicators the parallel matrix will live on
10832 .    seqmat - the input sequential matrices
10833 .    n - number of local columns (or `PETSC_DECIDE`)
10834 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10835 
10836    Output Parameter:
10837 .    mpimat - the parallel matrix generated
10838 
10839     Level: developer
10840 
10841    Note:
10842     The number of columns of the matrix in EACH processor MUST be the same.
10843 
10844 .seealso: [](ch_matrices), `Mat`
10845 @*/
10846 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10847 {
10848   PetscMPIInt size;
10849 
10850   PetscFunctionBegin;
10851   PetscCallMPI(MPI_Comm_size(comm, &size));
10852   if (size == 1) {
10853     if (reuse == MAT_INITIAL_MATRIX) {
10854       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10855     } else {
10856       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10857     }
10858     PetscFunctionReturn(PETSC_SUCCESS);
10859   }
10860 
10861   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");
10862 
10863   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10864   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10865   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10866   PetscFunctionReturn(PETSC_SUCCESS);
10867 }
10868 
10869 /*@
10870      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10871 
10872     Collective
10873 
10874    Input Parameters:
10875 +    A   - the matrix to create subdomains from
10876 -    N   - requested number of subdomains
10877 
10878    Output Parameters:
10879 +    n   - number of subdomains resulting on this MPI process
10880 -    iss - `IS` list with indices of subdomains on this MPI process
10881 
10882     Level: advanced
10883 
10884     Note:
10885     The number of subdomains must be smaller than the communicator size
10886 
10887 .seealso: [](ch_matrices), `Mat`, `IS`
10888 @*/
10889 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10890 {
10891   MPI_Comm    comm, subcomm;
10892   PetscMPIInt size, rank, color;
10893   PetscInt    rstart, rend, k;
10894 
10895   PetscFunctionBegin;
10896   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10897   PetscCallMPI(MPI_Comm_size(comm, &size));
10898   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10899   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);
10900   *n    = 1;
10901   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10902   color = rank / k;
10903   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10904   PetscCall(PetscMalloc1(1, iss));
10905   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10906   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10907   PetscCallMPI(MPI_Comm_free(&subcomm));
10908   PetscFunctionReturn(PETSC_SUCCESS);
10909 }
10910 
10911 /*@
10912    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10913 
10914    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10915    If they are not the same, uses `MatMatMatMult()`.
10916 
10917    Once the coarse grid problem is constructed, correct for interpolation operators
10918    that are not of full rank, which can legitimately happen in the case of non-nested
10919    geometric multigrid.
10920 
10921    Input Parameters:
10922 +  restrct - restriction operator
10923 .  dA - fine grid matrix
10924 .  interpolate - interpolation operator
10925 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10926 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10927 
10928    Output Parameter:
10929 .  A - the Galerkin coarse matrix
10930 
10931    Options Database Key:
10932 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10933 
10934    Level: developer
10935 
10936 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10937 @*/
10938 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10939 {
10940   IS  zerorows;
10941   Vec diag;
10942 
10943   PetscFunctionBegin;
10944   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10945   /* Construct the coarse grid matrix */
10946   if (interpolate == restrct) {
10947     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10948   } else {
10949     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10950   }
10951 
10952   /* If the interpolation matrix is not of full rank, A will have zero rows.
10953      This can legitimately happen in the case of non-nested geometric multigrid.
10954      In that event, we set the rows of the matrix to the rows of the identity,
10955      ignoring the equations (as the RHS will also be zero). */
10956 
10957   PetscCall(MatFindZeroRows(*A, &zerorows));
10958 
10959   if (zerorows != NULL) { /* if there are any zero rows */
10960     PetscCall(MatCreateVecs(*A, &diag, NULL));
10961     PetscCall(MatGetDiagonal(*A, diag));
10962     PetscCall(VecISSet(diag, zerorows, 1.0));
10963     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10964     PetscCall(VecDestroy(&diag));
10965     PetscCall(ISDestroy(&zerorows));
10966   }
10967   PetscFunctionReturn(PETSC_SUCCESS);
10968 }
10969 
10970 /*@C
10971     MatSetOperation - Allows user to set a matrix operation for any matrix type
10972 
10973    Logically Collective
10974 
10975     Input Parameters:
10976 +   mat - the matrix
10977 .   op - the name of the operation
10978 -   f - the function that provides the operation
10979 
10980    Level: developer
10981 
10982     Usage:
10983 .vb
10984   extern PetscErrorCode usermult(Mat, Vec, Vec);
10985 
10986   PetscCall(MatCreateXXX(comm, ..., &A));
10987   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10988 .ve
10989 
10990     Notes:
10991     See the file `include/petscmat.h` for a complete list of matrix
10992     operations, which all have the form MATOP_<OPERATION>, where
10993     <OPERATION> is the name (in all capital letters) of the
10994     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10995 
10996     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10997     sequence as the usual matrix interface routines, since they
10998     are intended to be accessed via the usual matrix interface
10999     routines, e.g.,
11000 .vb
11001   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11002 .ve
11003 
11004     In particular each function MUST return `PETSC_SUCCESS` on success and
11005     nonzero on failure.
11006 
11007     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11008 
11009 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11010 @*/
11011 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11012 {
11013   PetscFunctionBegin;
11014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11015   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11016   (((void (**)(void))mat->ops)[op]) = f;
11017   PetscFunctionReturn(PETSC_SUCCESS);
11018 }
11019 
11020 /*@C
11021     MatGetOperation - Gets a matrix operation for any matrix type.
11022 
11023     Not Collective
11024 
11025     Input Parameters:
11026 +   mat - the matrix
11027 -   op - the name of the operation
11028 
11029     Output Parameter:
11030 .   f - the function that provides the operation
11031 
11032     Level: developer
11033 
11034     Usage:
11035 .vb
11036       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11037       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11038 .ve
11039 
11040     Notes:
11041     See the file include/petscmat.h for a complete list of matrix
11042     operations, which all have the form MATOP_<OPERATION>, where
11043     <OPERATION> is the name (in all capital letters) of the
11044     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11045 
11046     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11047 
11048 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11049 @*/
11050 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11051 {
11052   PetscFunctionBegin;
11053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11054   *f = (((void (**)(void))mat->ops)[op]);
11055   PetscFunctionReturn(PETSC_SUCCESS);
11056 }
11057 
11058 /*@
11059     MatHasOperation - Determines whether the given matrix supports the particular operation.
11060 
11061    Not Collective
11062 
11063    Input Parameters:
11064 +  mat - the matrix
11065 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11066 
11067    Output Parameter:
11068 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11069 
11070    Level: advanced
11071 
11072    Note:
11073    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11074 
11075 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11076 @*/
11077 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11078 {
11079   PetscFunctionBegin;
11080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11081   PetscValidBoolPointer(has, 3);
11082   if (mat->ops->hasoperation) {
11083     PetscUseTypeMethod(mat, hasoperation, op, has);
11084   } else {
11085     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11086     else {
11087       *has = PETSC_FALSE;
11088       if (op == MATOP_CREATE_SUBMATRIX) {
11089         PetscMPIInt size;
11090 
11091         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11092         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11093       }
11094     }
11095   }
11096   PetscFunctionReturn(PETSC_SUCCESS);
11097 }
11098 
11099 /*@
11100     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11101 
11102    Collective
11103 
11104    Input Parameter:
11105 .  mat - the matrix
11106 
11107    Output Parameter:
11108 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11109 
11110    Level: beginner
11111 
11112 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11113 @*/
11114 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11115 {
11116   PetscFunctionBegin;
11117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11118   PetscValidType(mat, 1);
11119   PetscValidBoolPointer(cong, 2);
11120   if (!mat->rmap || !mat->cmap) {
11121     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11122     PetscFunctionReturn(PETSC_SUCCESS);
11123   }
11124   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11125     PetscCall(PetscLayoutSetUp(mat->rmap));
11126     PetscCall(PetscLayoutSetUp(mat->cmap));
11127     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11128     if (*cong) mat->congruentlayouts = 1;
11129     else mat->congruentlayouts = 0;
11130   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11131   PetscFunctionReturn(PETSC_SUCCESS);
11132 }
11133 
11134 PetscErrorCode MatSetInf(Mat A)
11135 {
11136   PetscFunctionBegin;
11137   PetscUseTypeMethod(A, setinf);
11138   PetscFunctionReturn(PETSC_SUCCESS);
11139 }
11140 
11141 /*@C
11142    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
11143    and possibly removes small values from the graph structure.
11144 
11145    Collective
11146 
11147    Input Parameters:
11148 +  A - the matrix
11149 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11150 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11151 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11152 
11153    Output Parameter:
11154 .  graph - the resulting graph
11155 
11156    Level: advanced
11157 
11158 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11159 @*/
11160 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11161 {
11162   PetscFunctionBegin;
11163   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11164   PetscValidType(A, 1);
11165   PetscValidLogicalCollectiveBool(A, scale, 3);
11166   PetscValidPointer(graph, 5);
11167   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11168   PetscFunctionReturn(PETSC_SUCCESS);
11169 }
11170 
11171 /*@
11172   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11173   meaning the same memory is used for the matrix, and no new memory is allocated.
11174 
11175   Collective
11176 
11177   Input Parameter:
11178 . A - the matrix
11179 
11180   Level: intermediate
11181 
11182   Developer Note:
11183   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11184   of the arrays in the data structure are unneeded.
11185 
11186 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11187 @*/
11188 PetscErrorCode MatEliminateZeros(Mat A)
11189 {
11190   PetscFunctionBegin;
11191   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11192   PetscUseTypeMethod(A, eliminatezeros);
11193   PetscFunctionReturn(PETSC_SUCCESS);
11194 }
11195