xref: /petsc/src/mat/interface/matrix.c (revision f13b9fe212e71c763a9b4b76f918e558465d0fc2)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](chapter_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](chapter_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameter:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameter:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903    MatSetUp - Sets up the internal matrix data structures for later use.
904 
905    Collective
906 
907    Input Parameter:
908 .  A - the matrix
909 
910    Level: intermediate
911 
912    Notes:
913    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
914    setting values in the matrix.
915 
916    If a suitable preallocation routine is used, this function does not need to be called.
917 
918    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
919 
920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
921 @*/
922 PetscErrorCode MatSetUp(Mat A)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   if (!((PetscObject)A)->type_name) {
927     PetscMPIInt size;
928 
929     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
930     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
931   }
932   if (!A->preallocated) PetscTryTypeMethod(A, setup);
933   PetscCall(PetscLayoutSetUp(A->rmap));
934   PetscCall(PetscLayoutSetUp(A->cmap));
935   A->preallocated = PETSC_TRUE;
936   PetscFunctionReturn(PETSC_SUCCESS);
937 }
938 
939 #if defined(PETSC_HAVE_SAWS)
940   #include <petscviewersaws.h>
941 #endif
942 
943 /*@C
944    MatViewFromOptions - View properties of the matrix based on options set in the options database
945 
946    Collective
947 
948    Input Parameters:
949 +  A - the matrix
950 .  obj - optional additional object that provides the options prefix to use
951 -  name - command line option
952 
953   Options Database Key:
954 .  -mat_view [viewertype]:... - the viewer and its options
955 
956    Level: intermediate
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
971 @*/
972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
977   PetscFunctionReturn(PETSC_SUCCESS);
978 }
979 
980 /*@C
981    MatView - display information about a matrix in a variety ways
982 
983    Collective
984 
985    Input Parameters:
986 +  mat - the matrix
987 -  viewer - visualization context
988 
989    Options Database Keys:
990 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
991 .  -mat_view ::ascii_info_detail - Prints more detailed info
992 .  -mat_view - Prints matrix in ASCII format
993 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
994 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
995 .  -display <name> - Sets display name (default is host)
996 .  -draw_pause <sec> - Sets number of seconds to pause after display
997 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
998 .  -viewer_socket_machine <machine> -
999 .  -viewer_socket_port <port> -
1000 .  -mat_view binary - save matrix to file in binary format
1001 -  -viewer_binary_filename <name> -
1002 
1003    Level: beginner
1004 
1005   Notes:
1006   The available visualization contexts include
1007 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1008 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1009 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1010 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1011 
1012    The user can open alternative visualization contexts with
1013 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1014 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1015          specified file; corresponding input uses MatLoad()
1016 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1017          an X window display
1018 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1019          Currently only the sequential dense and AIJ
1020          matrix types support the Socket viewer.
1021 
1022    The user can call `PetscViewerPushFormat()` to specify the output
1023    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1024    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1025 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1026 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1027 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1028 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1029          format common among all matrix types
1030 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1031          format (which is in many cases the same as the default)
1032 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1033          size and structure (not the matrix entries)
1034 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1035          the matrix structure
1036 
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072 
1073   PetscCall(PetscViewerGetFormat(viewer, &format));
1074   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1075   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1076 
1077   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1080   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1081 
1082   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1083   if (isascii) {
1084     if (!mat->preallocated) {
1085       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1086       PetscFunctionReturn(PETSC_SUCCESS);
1087     }
1088     if (!mat->assembled) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1094       MatNullSpace nullsp, transnullsp;
1095 
1096       PetscCall(PetscViewerASCIIPushTab(viewer));
1097       PetscCall(MatGetSize(mat, &rows, &cols));
1098       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1099       if (rbs != 1 || cbs != 1) {
1100         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1101         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1102       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1103       if (mat->factortype) {
1104         MatSolverType solver;
1105         PetscCall(MatFactorGetSolverType(mat, &solver));
1106         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1107       }
1108       if (mat->ops->getinfo) {
1109         MatInfo info;
1110         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1112         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1113       }
1114       PetscCall(MatGetNullSpace(mat, &nullsp));
1115       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1117       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1118       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatProductView(mat, viewer));
1122       PetscCall(PetscViewerASCIIPopTab(viewer));
1123     }
1124   } else if (issaws) {
1125 #if defined(PETSC_HAVE_SAWS)
1126     PetscMPIInt rank;
1127 
1128     PetscCall(PetscObjectName((PetscObject)mat));
1129     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1130     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1131 #endif
1132   } else if (isstring) {
1133     const char *type;
1134     PetscCall(MatGetType(mat, &type));
1135     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1136     PetscTryTypeMethod(mat, view, viewer);
1137   }
1138   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1139     PetscCall(PetscViewerASCIIPushTab(viewer));
1140     PetscUseTypeMethod(mat, viewnative, viewer);
1141     PetscCall(PetscViewerASCIIPopTab(viewer));
1142   } else if (mat->ops->view) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, view, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   }
1147   if (isascii) {
1148     PetscCall(PetscViewerGetFormat(viewer, &format));
1149     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1152   PetscFunctionReturn(PETSC_SUCCESS);
1153 }
1154 
1155 #if defined(PETSC_USE_DEBUG)
1156   #include <../src/sys/totalview/tv_data_display.h>
1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1158 {
1159   TV_add_row("Local rows", "int", &mat->rmap->n);
1160   TV_add_row("Local columns", "int", &mat->cmap->n);
1161   TV_add_row("Global rows", "int", &mat->rmap->N);
1162   TV_add_row("Global columns", "int", &mat->cmap->N);
1163   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1164   return TV_format_OK;
1165 }
1166 #endif
1167 
1168 /*@C
1169    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1170    with `MatView()`.  The matrix format is determined from the options database.
1171    Generates a parallel MPI matrix if the communicator has more than one
1172    processor.  The default matrix type is `MATAIJ`.
1173 
1174    Collective
1175 
1176    Input Parameters:
1177 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1178             or some related function before a call to `MatLoad()`
1179 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1180 
1181    Options Database Keys:
1182    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1183    block size
1184 .    -matload_block_size <bs> - set block size
1185 
1186    Level: beginner
1187 
1188    Notes:
1189    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1190    `Mat` before calling this routine if you wish to set it from the options database.
1191 
1192    `MatLoad()` automatically loads into the options database any options
1193    given in the file filename.info where filename is the name of the file
1194    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1195    file will be ignored if you use the -viewer_binary_skip_info option.
1196 
1197    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1198    sets the default matrix type AIJ and sets the local and global sizes.
1199    If type and/or size is already set, then the same are used.
1200 
1201    In parallel, each processor can load a subset of rows (or the
1202    entire matrix).  This routine is especially useful when a large
1203    matrix is stored on disk and only part of it is desired on each
1204    processor.  For example, a parallel solver may access only some of
1205    the rows from each processor.  The algorithm used here reads
1206    relatively small blocks of data rather than reading the entire
1207    matrix and then subsetting it.
1208 
1209    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1210    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1211    or the sequence like
1212 .vb
1213     `PetscViewer` v;
1214     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1215     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1216     `PetscViewerSetFromOptions`(v);
1217     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1218     `PetscViewerFileSetName`(v,"datafile");
1219 .ve
1220    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1221 $ -viewer_type {binary, hdf5}
1222 
1223    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1224    and src/mat/tutorials/ex10.c with the second approach.
1225 
1226    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1227    is read onto rank 0 and then shipped to its destination rank, one after another.
1228    Multiple objects, both matrices and vectors, can be stored within the same file.
1229    Their PetscObject name is ignored; they are loaded in the order of their storage.
1230 
1231    Most users should not need to know the details of the binary storage
1232    format, since `MatLoad()` and `MatView()` completely hide these details.
1233    But for anyone who's interested, the standard binary matrix storage
1234    format is
1235 
1236 .vb
1237     PetscInt    MAT_FILE_CLASSID
1238     PetscInt    number of rows
1239     PetscInt    number of columns
1240     PetscInt    total number of nonzeros
1241     PetscInt    *number nonzeros in each row
1242     PetscInt    *column indices of all nonzeros (starting index is zero)
1243     PetscScalar *values of all nonzeros
1244 .ve
1245 
1246    PETSc automatically does the byte swapping for
1247 machines that store the bytes reversed. Thus if you write your own binary
1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1249 and `PetscBinaryWrite()` to see how this may be done.
1250 
1251    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1252    Each processor's chunk is loaded independently by its owning rank.
1253    Multiple objects, both matrices and vectors, can be stored within the same file.
1254    They are looked up by their PetscObject name.
1255 
1256    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1257    by default the same structure and naming of the AIJ arrays and column count
1258    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1259 $    save example.mat A b -v7.3
1260    can be directly read by this routine (see Reference 1 for details).
1261 
1262    Depending on your MATLAB version, this format might be a default,
1263    otherwise you can set it as default in Preferences.
1264 
1265    Unless -nocompression flag is used to save the file in MATLAB,
1266    PETSc must be configured with ZLIB package.
1267 
1268    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1269 
1270    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1271 
1272    Corresponding `MatView()` is not yet implemented.
1273 
1274    The loaded matrix is actually a transpose of the original one in MATLAB,
1275    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1276    With this format, matrix is automatically transposed by PETSc,
1277    unless the matrix is marked as SPD or symmetric
1278    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1279 
1280    References:
1281 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1282 
1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1284  @*/
1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1286 {
1287   PetscBool flg;
1288 
1289   PetscFunctionBegin;
1290   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1291   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1292 
1293   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1294 
1295   flg = PETSC_FALSE;
1296   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1297   if (flg) {
1298     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1300   }
1301   flg = PETSC_FALSE;
1302   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1303   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1304 
1305   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1306   PetscUseTypeMethod(mat, load, viewer);
1307   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1308   PetscFunctionReturn(PETSC_SUCCESS);
1309 }
1310 
1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1312 {
1313   Mat_Redundant *redund = *redundant;
1314 
1315   PetscFunctionBegin;
1316   if (redund) {
1317     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1318       PetscCall(ISDestroy(&redund->isrow));
1319       PetscCall(ISDestroy(&redund->iscol));
1320       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1321     } else {
1322       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1323       PetscCall(PetscFree(redund->sbuf_j));
1324       PetscCall(PetscFree(redund->sbuf_a));
1325       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1326         PetscCall(PetscFree(redund->rbuf_j[i]));
1327         PetscCall(PetscFree(redund->rbuf_a[i]));
1328       }
1329       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1330     }
1331 
1332     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1333     PetscCall(PetscFree(redund));
1334   }
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 /*@C
1339    MatDestroy - Frees space taken by a matrix.
1340 
1341    Collective
1342 
1343    Input Parameter:
1344 .  A - the matrix
1345 
1346    Level: beginner
1347 
1348    Developer Note:
1349    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1350    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1351    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1352    if changes are needed here.
1353 
1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1355 @*/
1356 PetscErrorCode MatDestroy(Mat *A)
1357 {
1358   PetscFunctionBegin;
1359   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1360   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1361   if (--((PetscObject)(*A))->refct > 0) {
1362     *A = NULL;
1363     PetscFunctionReturn(PETSC_SUCCESS);
1364   }
1365 
1366   /* if memory was published with SAWs then destroy it */
1367   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1368   PetscTryTypeMethod((*A), destroy);
1369 
1370   PetscCall(PetscFree((*A)->factorprefix));
1371   PetscCall(PetscFree((*A)->defaultvectype));
1372   PetscCall(PetscFree((*A)->defaultrandtype));
1373   PetscCall(PetscFree((*A)->bsizes));
1374   PetscCall(PetscFree((*A)->solvertype));
1375   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1376   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1377   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1378   PetscCall(MatProductClear(*A));
1379   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1382   PetscCall(MatDestroy(&(*A)->schur));
1383   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1384   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1385   PetscCall(PetscHeaderDestroy(A));
1386   PetscFunctionReturn(PETSC_SUCCESS);
1387 }
1388 
1389 /*@C
1390    MatSetValues - Inserts or adds a block of values into a matrix.
1391    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1392    MUST be called after all calls to `MatSetValues()` have been completed.
1393 
1394    Not Collective
1395 
1396    Input Parameters:
1397 +  mat - the matrix
1398 .  v - a logically two-dimensional array of values
1399 .  m - the number of rows
1400 .  idxm - the global indices of the rows
1401 .  n - the number of columns
1402 .  idxn - the global indices of the columns
1403 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1404 
1405    Level: beginner
1406 
1407    Notes:
1408    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1409 
1410    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1411    options cannot be mixed without intervening calls to the assembly
1412    routines.
1413 
1414    `MatSetValues()` uses 0-based row and column numbers in Fortran
1415    as well as in C.
1416 
1417    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1418    simply ignored. This allows easily inserting element stiffness matrices
1419    with homogeneous Dirchlet boundary conditions that you don't want represented
1420    in the matrix.
1421 
1422    Efficiency Alert:
1423    The routine `MatSetValuesBlocked()` may offer much better efficiency
1424    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1425 
1426    Developer Note:
1427    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1428    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1429 
1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1431           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1432 @*/
1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1434 {
1435   PetscFunctionBeginHot;
1436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1437   PetscValidType(mat, 1);
1438   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1439   PetscValidIntPointer(idxm, 3);
1440   PetscValidIntPointer(idxn, 5);
1441   MatCheckPreallocated(mat, 1);
1442 
1443   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1444   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1445 
1446   if (PetscDefined(USE_DEBUG)) {
1447     PetscInt i, j;
1448 
1449     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1450     for (i = 0; i < m; i++) {
1451       for (j = 0; j < n; j++) {
1452         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1453 #if defined(PETSC_USE_COMPLEX)
1454           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1455 #else
1456           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1457 #endif
1458       }
1459     }
1460     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1461     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1462   }
1463 
1464   if (mat->assembled) {
1465     mat->was_assembled = PETSC_TRUE;
1466     mat->assembled     = PETSC_FALSE;
1467   }
1468   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1469   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1470   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1471   PetscFunctionReturn(PETSC_SUCCESS);
1472 }
1473 
1474 /*@C
1475    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1476    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1477    MUST be called after all calls to `MatSetValues()` have been completed.
1478 
1479    Not Collective
1480 
1481    Input Parameters:
1482 +  mat - the matrix
1483 .  v - a logically two-dimensional array of values
1484 .  ism - the rows to provide
1485 .  isn - the columns to provide
1486 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1487 
1488    Level: beginner
1489 
1490    Notes:
1491    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1492 
1493    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1494    options cannot be mixed without intervening calls to the assembly
1495    routines.
1496 
1497    `MatSetValues()` uses 0-based row and column numbers in Fortran
1498    as well as in C.
1499 
1500    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1501    simply ignored. This allows easily inserting element stiffness matrices
1502    with homogeneous Dirchlet boundary conditions that you don't want represented
1503    in the matrix.
1504 
1505    Efficiency Alert:
1506    The routine `MatSetValuesBlocked()` may offer much better efficiency
1507    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1508 
1509     This is currently not optimized for any particular `ISType`
1510 
1511    Developer Notes:
1512     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1513                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1514 
1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1516           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1517 @*/
1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1519 {
1520   PetscInt        m, n;
1521   const PetscInt *rows, *cols;
1522 
1523   PetscFunctionBeginHot;
1524   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1525   PetscCall(ISGetIndices(ism, &rows));
1526   PetscCall(ISGetIndices(isn, &cols));
1527   PetscCall(ISGetLocalSize(ism, &m));
1528   PetscCall(ISGetLocalSize(isn, &n));
1529   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1530   PetscCall(ISRestoreIndices(ism, &rows));
1531   PetscCall(ISRestoreIndices(isn, &cols));
1532   PetscFunctionReturn(PETSC_SUCCESS);
1533 }
1534 
1535 /*@
1536    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1537         values into a matrix
1538 
1539    Not Collective
1540 
1541    Input Parameters:
1542 +  mat - the matrix
1543 .  row - the (block) row to set
1544 -  v - a logically two-dimensional array of values
1545 
1546    Level: intermediate
1547 
1548    Notes:
1549    The values, `v`, are column-oriented (for the block version) and sorted
1550 
1551    All the nonzeros in the row must be provided
1552 
1553    The matrix must have previously had its column indices set, likely by having been assembled.
1554 
1555    The row must belong to this process
1556 
1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1558           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1559 @*/
1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1561 {
1562   PetscInt globalrow;
1563 
1564   PetscFunctionBegin;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscValidType(mat, 1);
1567   PetscValidScalarPointer(v, 3);
1568   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1569   PetscCall(MatSetValuesRow(mat, globalrow, v));
1570   PetscFunctionReturn(PETSC_SUCCESS);
1571 }
1572 
1573 /*@
1574    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1575         values into a matrix
1576 
1577    Not Collective
1578 
1579    Input Parameters:
1580 +  mat - the matrix
1581 .  row - the (block) row to set
1582 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1583 
1584    Level: advanced
1585 
1586    Notes:
1587    The values, `v`, are column-oriented for the block version.
1588 
1589    All the nonzeros in the row must be provided
1590 
1591    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1592 
1593    The row must belong to this process
1594 
1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1596           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1597 @*/
1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1599 {
1600   PetscFunctionBeginHot;
1601   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1602   PetscValidType(mat, 1);
1603   MatCheckPreallocated(mat, 1);
1604   PetscValidScalarPointer(v, 3);
1605   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1606   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1607   mat->insertmode = INSERT_VALUES;
1608 
1609   if (mat->assembled) {
1610     mat->was_assembled = PETSC_TRUE;
1611     mat->assembled     = PETSC_FALSE;
1612   }
1613   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1614   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1615   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1616   PetscFunctionReturn(PETSC_SUCCESS);
1617 }
1618 
1619 /*@
1620    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1621      Using structured grid indexing
1622 
1623    Not Collective
1624 
1625    Input Parameters:
1626 +  mat - the matrix
1627 .  m - number of rows being entered
1628 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1629 .  n - number of columns being entered
1630 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1631 .  v - a logically two-dimensional array of values
1632 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1633 
1634    Level: beginner
1635 
1636    Notes:
1637    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1638 
1639    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1640    options cannot be mixed without intervening calls to the assembly
1641    routines.
1642 
1643    The grid coordinates are across the entire grid, not just the local portion
1644 
1645    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1646    as well as in C.
1647 
1648    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1649 
1650    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1651    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1652 
1653    The columns and rows in the stencil passed in MUST be contained within the
1654    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1655    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1656    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1657    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1658 
1659    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1660    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1661    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1662    `DM_BOUNDARY_PERIODIC` boundary type.
1663 
1664    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1665    a single value per point) you can skip filling those indices.
1666 
1667    Inspired by the structured grid interface to the HYPRE package
1668    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1669 
1670    Efficiency Alert:
1671    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1672    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1673 
1674    Fortran Note:
1675    `idxm` and `idxn` should be declared as
1676 $     MatStencil idxm(4,m),idxn(4,n)
1677    and the values inserted using
1678 .vb
1679     idxm(MatStencil_i,1) = i
1680     idxm(MatStencil_j,1) = j
1681     idxm(MatStencil_k,1) = k
1682     idxm(MatStencil_c,1) = c
1683     etc
1684 .ve
1685 
1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1687           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1688 @*/
1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1690 {
1691   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1692   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1693   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1694 
1695   PetscFunctionBegin;
1696   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1698   PetscValidType(mat, 1);
1699   PetscValidPointer(idxm, 3);
1700   PetscValidPointer(idxn, 5);
1701 
1702   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1703     jdxm = buf;
1704     jdxn = buf + m;
1705   } else {
1706     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1707     jdxm = bufm;
1708     jdxn = bufn;
1709   }
1710   for (i = 0; i < m; i++) {
1711     for (j = 0; j < 3 - sdim; j++) dxm++;
1712     tmp = *dxm++ - starts[0];
1713     for (j = 0; j < dim - 1; j++) {
1714       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1715       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1716     }
1717     if (mat->stencil.noc) dxm++;
1718     jdxm[i] = tmp;
1719   }
1720   for (i = 0; i < n; i++) {
1721     for (j = 0; j < 3 - sdim; j++) dxn++;
1722     tmp = *dxn++ - starts[0];
1723     for (j = 0; j < dim - 1; j++) {
1724       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1725       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1726     }
1727     if (mat->stencil.noc) dxn++;
1728     jdxn[i] = tmp;
1729   }
1730   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1731   PetscCall(PetscFree2(bufm, bufn));
1732   PetscFunctionReturn(PETSC_SUCCESS);
1733 }
1734 
1735 /*@
1736    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1737      Using structured grid indexing
1738 
1739    Not Collective
1740 
1741    Input Parameters:
1742 +  mat - the matrix
1743 .  m - number of rows being entered
1744 .  idxm - grid coordinates for matrix rows being entered
1745 .  n - number of columns being entered
1746 .  idxn - grid coordinates for matrix columns being entered
1747 .  v - a logically two-dimensional array of values
1748 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1749 
1750    Level: beginner
1751 
1752    Notes:
1753    By default the values, `v`, are row-oriented and unsorted.
1754    See `MatSetOption()` for other options.
1755 
1756    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1757    options cannot be mixed without intervening calls to the assembly
1758    routines.
1759 
1760    The grid coordinates are across the entire grid, not just the local portion
1761 
1762    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1763    as well as in C.
1764 
1765    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1766 
1767    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1768    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1769 
1770    The columns and rows in the stencil passed in MUST be contained within the
1771    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1772    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1773    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1774    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1775 
1776    Negative indices may be passed in idxm and idxn, these rows and columns are
1777    simply ignored. This allows easily inserting element stiffness matrices
1778    with homogeneous Dirchlet boundary conditions that you don't want represented
1779    in the matrix.
1780 
1781    Inspired by the structured grid interface to the HYPRE package
1782    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1783 
1784    Fortran Note:
1785    `idxm` and `idxn` should be declared as
1786 $     MatStencil idxm(4,m),idxn(4,n)
1787    and the values inserted using
1788 .vb
1789     idxm(MatStencil_i,1) = i
1790     idxm(MatStencil_j,1) = j
1791     idxm(MatStencil_k,1) = k
1792    etc
1793 .ve
1794 
1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1796           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1797           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1798 @*/
1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscValidPointer(idxm, 3);
1810   PetscValidPointer(idxn, 5);
1811   PetscValidScalarPointer(v, 6);
1812 
1813   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1814     jdxm = buf;
1815     jdxn = buf + m;
1816   } else {
1817     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1818     jdxm = bufm;
1819     jdxn = bufn;
1820   }
1821   for (i = 0; i < m; i++) {
1822     for (j = 0; j < 3 - sdim; j++) dxm++;
1823     tmp = *dxm++ - starts[0];
1824     for (j = 0; j < sdim - 1; j++) {
1825       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1826       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1827     }
1828     dxm++;
1829     jdxm[i] = tmp;
1830   }
1831   for (i = 0; i < n; i++) {
1832     for (j = 0; j < 3 - sdim; j++) dxn++;
1833     tmp = *dxn++ - starts[0];
1834     for (j = 0; j < sdim - 1; j++) {
1835       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1836       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1837     }
1838     dxn++;
1839     jdxn[i] = tmp;
1840   }
1841   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1842   PetscCall(PetscFree2(bufm, bufn));
1843   PetscFunctionReturn(PETSC_SUCCESS);
1844 }
1845 
1846 /*@
1847    MatSetStencil - Sets the grid information for setting values into a matrix via
1848         `MatSetValuesStencil()`
1849 
1850    Not Collective
1851 
1852    Input Parameters:
1853 +  mat - the matrix
1854 .  dim - dimension of the grid 1, 2, or 3
1855 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1856 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1857 -  dof - number of degrees of freedom per node
1858 
1859    Level: beginner
1860 
1861    Notes:
1862    Inspired by the structured grid interface to the HYPRE package
1863    (www.llnl.gov/CASC/hyper)
1864 
1865    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1866    user.
1867 
1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1869           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1870 @*/
1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1872 {
1873   PetscFunctionBegin;
1874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1875   PetscValidIntPointer(dims, 3);
1876   PetscValidIntPointer(starts, 4);
1877 
1878   mat->stencil.dim = dim + (dof > 1);
1879   for (PetscInt i = 0; i < dim; i++) {
1880     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1881     mat->stencil.starts[i] = starts[dim - i - 1];
1882   }
1883   mat->stencil.dims[dim]   = dof;
1884   mat->stencil.starts[dim] = 0;
1885   mat->stencil.noc         = (PetscBool)(dof == 1);
1886   PetscFunctionReturn(PETSC_SUCCESS);
1887 }
1888 
1889 /*@C
1890    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1891 
1892    Not Collective
1893 
1894    Input Parameters:
1895 +  mat - the matrix
1896 .  v - a logically two-dimensional array of values
1897 .  m  - the number of block rows
1898 .  idxm - the global block indices
1899 .  n - the number of block columns
1900 .  idxn - the global block indices
1901 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1902 
1903    Level: intermediate
1904 
1905    Notes:
1906    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1907    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1908 
1909    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1910    NOT the total number of rows/columns; for example, if the block size is 2 and
1911    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1912    The values in idxm would be 1 2; that is the first index for each block divided by
1913    the block size.
1914 
1915    You must call `MatSetBlockSize()` when constructing this matrix (before
1916    preallocating it).
1917 
1918    By default the values, `v`, are row-oriented, so the layout of
1919    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1920 
1921    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1922    options cannot be mixed without intervening calls to the assembly
1923    routines.
1924 
1925    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1926    as well as in C.
1927 
1928    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1929    simply ignored. This allows easily inserting element stiffness matrices
1930    with homogeneous Dirchlet boundary conditions that you don't want represented
1931    in the matrix.
1932 
1933    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1934    internal searching must be done to determine where to place the
1935    data in the matrix storage space.  By instead inserting blocks of
1936    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1937    reduced.
1938 
1939    Example:
1940 .vb
1941    Suppose m=n=2 and block size(bs) = 2 The array is
1942 
1943    1  2  | 3  4
1944    5  6  | 7  8
1945    - - - | - - -
1946    9  10 | 11 12
1947    13 14 | 15 16
1948 
1949    v[] should be passed in like
1950    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1951 
1952   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1953    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1954 .ve
1955 
1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1957 @*/
1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1959 {
1960   PetscFunctionBeginHot;
1961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1962   PetscValidType(mat, 1);
1963   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1964   PetscValidIntPointer(idxm, 3);
1965   PetscValidIntPointer(idxn, 5);
1966   MatCheckPreallocated(mat, 1);
1967   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1968   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1969   if (PetscDefined(USE_DEBUG)) {
1970     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1971     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1972   }
1973   if (PetscDefined(USE_DEBUG)) {
1974     PetscInt rbs, cbs, M, N, i;
1975     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1976     PetscCall(MatGetSize(mat, &M, &N));
1977     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1978     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1979   }
1980   if (mat->assembled) {
1981     mat->was_assembled = PETSC_TRUE;
1982     mat->assembled     = PETSC_FALSE;
1983   }
1984   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1985   if (mat->ops->setvaluesblocked) {
1986     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1987   } else {
1988     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1989     PetscInt i, j, bs, cbs;
1990 
1991     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1992     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1993       iidxm = buf;
1994       iidxn = buf + m * bs;
1995     } else {
1996       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1997       iidxm = bufr;
1998       iidxn = bufc;
1999     }
2000     for (i = 0; i < m; i++) {
2001       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2002     }
2003     if (m != n || bs != cbs || idxm != idxn) {
2004       for (i = 0; i < n; i++) {
2005         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2006       }
2007     } else iidxn = iidxm;
2008     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2009     PetscCall(PetscFree2(bufr, bufc));
2010   }
2011   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2012   PetscFunctionReturn(PETSC_SUCCESS);
2013 }
2014 
2015 /*@C
2016    MatGetValues - Gets a block of local values from a matrix.
2017 
2018    Not Collective; can only return values that are owned by the give process
2019 
2020    Input Parameters:
2021 +  mat - the matrix
2022 .  v - a logically two-dimensional array for storing the values
2023 .  m  - the number of rows
2024 .  idxm - the  global indices of the rows
2025 .  n - the number of columns
2026 -  idxn - the global indices of the columns
2027 
2028    Level: advanced
2029 
2030    Notes:
2031      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2032      The values, `v`, are then returned in a row-oriented format,
2033      analogous to that used by default in `MatSetValues()`.
2034 
2035      `MatGetValues()` uses 0-based row and column numbers in
2036      Fortran as well as in C.
2037 
2038      `MatGetValues()` requires that the matrix has been assembled
2039      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2040      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2041      without intermediate matrix assembly.
2042 
2043      Negative row or column indices will be ignored and those locations in `v` will be
2044      left unchanged.
2045 
2046      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2047      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2048      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2049 
2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2051 @*/
2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2053 {
2054   PetscFunctionBegin;
2055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2056   PetscValidType(mat, 1);
2057   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2058   PetscValidIntPointer(idxm, 3);
2059   PetscValidIntPointer(idxn, 5);
2060   PetscValidScalarPointer(v, 6);
2061   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2062   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2063   MatCheckPreallocated(mat, 1);
2064 
2065   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2066   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2067   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2068   PetscFunctionReturn(PETSC_SUCCESS);
2069 }
2070 
2071 /*@C
2072    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2073      defined previously by `MatSetLocalToGlobalMapping()`
2074 
2075    Not Collective
2076 
2077    Input Parameters:
2078 +  mat - the matrix
2079 .  nrow - number of rows
2080 .  irow - the row local indices
2081 .  ncol - number of columns
2082 -  icol - the column local indices
2083 
2084    Output Parameter:
2085 .  y -  a logically two-dimensional array of values
2086 
2087    Level: advanced
2088 
2089    Notes:
2090      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2091 
2092      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2093      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2094      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2095      with `MatSetLocalToGlobalMapping()`.
2096 
2097    Developer Note:
2098       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2099       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2100 
2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2102           `MatSetValuesLocal()`, `MatGetValues()`
2103 @*/
2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2105 {
2106   PetscFunctionBeginHot;
2107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2108   PetscValidType(mat, 1);
2109   MatCheckPreallocated(mat, 1);
2110   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2111   PetscValidIntPointer(irow, 3);
2112   PetscValidIntPointer(icol, 5);
2113   if (PetscDefined(USE_DEBUG)) {
2114     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2115     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2116   }
2117   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2118   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2119   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2120   else {
2121     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2122     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2123       irowm = buf;
2124       icolm = buf + nrow;
2125     } else {
2126       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2127       irowm = bufr;
2128       icolm = bufc;
2129     }
2130     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2131     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2133     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2134     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2135     PetscCall(PetscFree2(bufr, bufc));
2136   }
2137   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2138   PetscFunctionReturn(PETSC_SUCCESS);
2139 }
2140 
2141 /*@
2142   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2143   the same size. Currently, this can only be called once and creates the given matrix.
2144 
2145   Not Collective
2146 
2147   Input Parameters:
2148 + mat - the matrix
2149 . nb - the number of blocks
2150 . bs - the number of rows (and columns) in each block
2151 . rows - a concatenation of the rows for each block
2152 - v - a concatenation of logically two-dimensional arrays of values
2153 
2154   Level: advanced
2155 
2156   Note:
2157   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2158 
2159   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2160 
2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2162           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2163 @*/
2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2165 {
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2168   PetscValidType(mat, 1);
2169   PetscValidIntPointer(rows, 4);
2170   PetscValidScalarPointer(v, 5);
2171   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2172 
2173   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2174   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2175   else {
2176     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2177   }
2178   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2179   PetscFunctionReturn(PETSC_SUCCESS);
2180 }
2181 
2182 /*@
2183    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2184    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2185    using a local (per-processor) numbering.
2186 
2187    Not Collective
2188 
2189    Input Parameters:
2190 +  x - the matrix
2191 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2192 -  cmapping - column mapping
2193 
2194    Level: intermediate
2195 
2196    Note:
2197    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2198 
2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2200 @*/
2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2202 {
2203   PetscFunctionBegin;
2204   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2205   PetscValidType(x, 1);
2206   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2207   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2208   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2209   else {
2210     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2212   }
2213   PetscFunctionReturn(PETSC_SUCCESS);
2214 }
2215 
2216 /*@
2217    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2218 
2219    Not Collective
2220 
2221    Input Parameter:
2222 .  A - the matrix
2223 
2224    Output Parameters:
2225 + rmapping - row mapping
2226 - cmapping - column mapping
2227 
2228    Level: advanced
2229 
2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2236   PetscValidType(A, 1);
2237   if (rmapping) {
2238     PetscValidPointer(rmapping, 2);
2239     *rmapping = A->rmap->mapping;
2240   }
2241   if (cmapping) {
2242     PetscValidPointer(cmapping, 3);
2243     *cmapping = A->cmap->mapping;
2244   }
2245   PetscFunctionReturn(PETSC_SUCCESS);
2246 }
2247 
2248 /*@
2249    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2250 
2251    Logically Collective
2252 
2253    Input Parameters:
2254 +  A - the matrix
2255 . rmap - row layout
2256 - cmap - column layout
2257 
2258    Level: advanced
2259 
2260    Note:
2261    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2262 
2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2264 @*/
2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2269   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2270   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2271   PetscFunctionReturn(PETSC_SUCCESS);
2272 }
2273 
2274 /*@
2275    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2276 
2277    Not Collective
2278 
2279    Input Parameter:
2280 .  A - the matrix
2281 
2282    Output Parameters:
2283 + rmap - row layout
2284 - cmap - column layout
2285 
2286    Level: advanced
2287 
2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2289 @*/
2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2291 {
2292   PetscFunctionBegin;
2293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2294   PetscValidType(A, 1);
2295   if (rmap) {
2296     PetscValidPointer(rmap, 2);
2297     *rmap = A->rmap;
2298   }
2299   if (cmap) {
2300     PetscValidPointer(cmap, 3);
2301     *cmap = A->cmap;
2302   }
2303   PetscFunctionReturn(PETSC_SUCCESS);
2304 }
2305 
2306 /*@C
2307    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2308    using a local numbering of the nodes.
2309 
2310    Not Collective
2311 
2312    Input Parameters:
2313 +  mat - the matrix
2314 .  nrow - number of rows
2315 .  irow - the row local indices
2316 .  ncol - number of columns
2317 .  icol - the column local indices
2318 .  y -  a logically two-dimensional array of values
2319 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2320 
2321    Level: intermediate
2322 
2323    Notes:
2324    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2325       `MatSetUp()` before using this routine
2326 
2327    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2328 
2329    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2330    options cannot be mixed without intervening calls to the assembly
2331    routines.
2332 
2333    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2334    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2335 
2336    Developer Note:
2337     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2338                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2339 
2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2341           `MatGetValuesLocal()`
2342 @*/
2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2344 {
2345   PetscFunctionBeginHot;
2346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2347   PetscValidType(mat, 1);
2348   MatCheckPreallocated(mat, 1);
2349   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2350   PetscValidIntPointer(irow, 3);
2351   PetscValidIntPointer(icol, 5);
2352   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2353   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2354   if (PetscDefined(USE_DEBUG)) {
2355     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2356     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2357   }
2358 
2359   if (mat->assembled) {
2360     mat->was_assembled = PETSC_TRUE;
2361     mat->assembled     = PETSC_FALSE;
2362   }
2363   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2364   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2365   else {
2366     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2367     const PetscInt *irowm, *icolm;
2368 
2369     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2370       bufr  = buf;
2371       bufc  = buf + nrow;
2372       irowm = bufr;
2373       icolm = bufc;
2374     } else {
2375       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2376       irowm = bufr;
2377       icolm = bufc;
2378     }
2379     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2380     else irowm = irow;
2381     if (mat->cmap->mapping) {
2382       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2383         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2384       } else icolm = irowm;
2385     } else icolm = icol;
2386     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2387     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2388   }
2389   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2390   PetscFunctionReturn(PETSC_SUCCESS);
2391 }
2392 
2393 /*@C
2394    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2395    using a local ordering of the nodes a block at a time.
2396 
2397    Not Collective
2398 
2399    Input Parameters:
2400 +  x - the matrix
2401 .  nrow - number of rows
2402 .  irow - the row local indices
2403 .  ncol - number of columns
2404 .  icol - the column local indices
2405 .  y -  a logically two-dimensional array of values
2406 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2407 
2408    Level: intermediate
2409 
2410    Notes:
2411    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2412       `MatSetUp()` before using this routine
2413 
2414    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2415       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2416 
2417    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2418    options cannot be mixed without intervening calls to the assembly
2419    routines.
2420 
2421    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2422    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2423 
2424    Developer Note:
2425     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2426                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2427 
2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2429           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2430 @*/
2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2432 {
2433   PetscFunctionBeginHot;
2434   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2435   PetscValidType(mat, 1);
2436   MatCheckPreallocated(mat, 1);
2437   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2438   PetscValidIntPointer(irow, 3);
2439   PetscValidIntPointer(icol, 5);
2440   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2441   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2442   if (PetscDefined(USE_DEBUG)) {
2443     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2444     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2445   }
2446 
2447   if (mat->assembled) {
2448     mat->was_assembled = PETSC_TRUE;
2449     mat->assembled     = PETSC_FALSE;
2450   }
2451   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2452     PetscInt irbs, rbs;
2453     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2454     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2455     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2456   }
2457   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2458     PetscInt icbs, cbs;
2459     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2460     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2461     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2462   }
2463   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2464   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2465   else {
2466     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2467     const PetscInt *irowm, *icolm;
2468 
2469     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2470       bufr  = buf;
2471       bufc  = buf + nrow;
2472       irowm = bufr;
2473       icolm = bufc;
2474     } else {
2475       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2476       irowm = bufr;
2477       icolm = bufc;
2478     }
2479     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2480     else irowm = irow;
2481     if (mat->cmap->mapping) {
2482       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2483         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2484       } else icolm = irowm;
2485     } else icolm = icol;
2486     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2487     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2488   }
2489   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2490   PetscFunctionReturn(PETSC_SUCCESS);
2491 }
2492 
2493 /*@
2494    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2495 
2496    Collective
2497 
2498    Input Parameters:
2499 +  mat - the matrix
2500 -  x   - the vector to be multiplied
2501 
2502    Output Parameter:
2503 .  y - the result
2504 
2505    Level: developer
2506 
2507    Note:
2508    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2509    call `MatMultDiagonalBlock`(A,y,y).
2510 
2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2512 @*/
2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2514 {
2515   PetscFunctionBegin;
2516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2517   PetscValidType(mat, 1);
2518   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2519   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2520 
2521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2523   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2524   MatCheckPreallocated(mat, 1);
2525 
2526   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2527   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2528   PetscFunctionReturn(PETSC_SUCCESS);
2529 }
2530 
2531 /*@
2532    MatMult - Computes the matrix-vector product, y = Ax.
2533 
2534    Neighbor-wise Collective
2535 
2536    Input Parameters:
2537 +  mat - the matrix
2538 -  x   - the vector to be multiplied
2539 
2540    Output Parameter:
2541 .  y - the result
2542 
2543    Level: beginner
2544 
2545    Note:
2546    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2547    call `MatMult`(A,y,y).
2548 
2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2550 @*/
2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2552 {
2553   PetscFunctionBegin;
2554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2555   PetscValidType(mat, 1);
2556   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2557   VecCheckAssembled(x);
2558   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2561   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2562   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2563   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2564   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2565   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2566   PetscCall(VecSetErrorIfLocked(y, 3));
2567   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2568   MatCheckPreallocated(mat, 1);
2569 
2570   PetscCall(VecLockReadPush(x));
2571   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2572   PetscUseTypeMethod(mat, mult, x, y);
2573   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2574   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2575   PetscCall(VecLockReadPop(x));
2576   PetscFunctionReturn(PETSC_SUCCESS);
2577 }
2578 
2579 /*@
2580    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2581 
2582    Neighbor-wise Collective
2583 
2584    Input Parameters:
2585 +  mat - the matrix
2586 -  x   - the vector to be multiplied
2587 
2588    Output Parameter:
2589 .  y - the result
2590 
2591    Level: beginner
2592 
2593    Notes:
2594    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2595    call `MatMultTranspose`(A,y,y).
2596 
2597    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2598    use `MatMultHermitianTranspose()`
2599 
2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2601 @*/
2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2603 {
2604   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2605 
2606   PetscFunctionBegin;
2607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2608   PetscValidType(mat, 1);
2609   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2610   VecCheckAssembled(x);
2611   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2612 
2613   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2614   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2615   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2616   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2617   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2618   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2619   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2620   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2621   MatCheckPreallocated(mat, 1);
2622 
2623   if (!mat->ops->multtranspose) {
2624     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2625     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2626   } else op = mat->ops->multtranspose;
2627   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2628   PetscCall(VecLockReadPush(x));
2629   PetscCall((*op)(mat, x, y));
2630   PetscCall(VecLockReadPop(x));
2631   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2632   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2633   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2634   PetscFunctionReturn(PETSC_SUCCESS);
2635 }
2636 
2637 /*@
2638    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2639 
2640    Neighbor-wise Collective
2641 
2642    Input Parameters:
2643 +  mat - the matrix
2644 -  x   - the vector to be multilplied
2645 
2646    Output Parameter:
2647 .  y - the result
2648 
2649    Level: beginner
2650 
2651    Notes:
2652    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2653    call `MatMultHermitianTranspose`(A,y,y).
2654 
2655    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2656 
2657    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2658 
2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2660 @*/
2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2662 {
2663   PetscFunctionBegin;
2664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2665   PetscValidType(mat, 1);
2666   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2667   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2668 
2669   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2670   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2671   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2672   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2673   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2674   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2675   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2676   MatCheckPreallocated(mat, 1);
2677 
2678   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2679 #if defined(PETSC_USE_COMPLEX)
2680   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2681     PetscCall(VecLockReadPush(x));
2682     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2683     else PetscUseTypeMethod(mat, mult, x, y);
2684     PetscCall(VecLockReadPop(x));
2685   } else {
2686     Vec w;
2687     PetscCall(VecDuplicate(x, &w));
2688     PetscCall(VecCopy(x, w));
2689     PetscCall(VecConjugate(w));
2690     PetscCall(MatMultTranspose(mat, w, y));
2691     PetscCall(VecDestroy(&w));
2692     PetscCall(VecConjugate(y));
2693   }
2694   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2695 #else
2696   PetscCall(MatMultTranspose(mat, x, y));
2697 #endif
2698   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2699   PetscFunctionReturn(PETSC_SUCCESS);
2700 }
2701 
2702 /*@
2703     MatMultAdd -  Computes v3 = v2 + A * v1.
2704 
2705     Neighbor-wise Collective
2706 
2707     Input Parameters:
2708 +   mat - the matrix
2709 .   v1 - the vector to be multiplied by `mat`
2710 -   v2 - the vector to be added to the result
2711 
2712     Output Parameter:
2713 .   v3 - the result
2714 
2715     Level: beginner
2716 
2717     Note:
2718     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2719     call `MatMultAdd`(A,v1,v2,v1).
2720 
2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2722 @*/
2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2724 {
2725   PetscFunctionBegin;
2726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2727   PetscValidType(mat, 1);
2728   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2729   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2730   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2731 
2732   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2734   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2735   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2736      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2737   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2738   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2739   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2740   MatCheckPreallocated(mat, 1);
2741 
2742   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2743   PetscCall(VecLockReadPush(v1));
2744   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2745   PetscCall(VecLockReadPop(v1));
2746   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2747   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2748   PetscFunctionReturn(PETSC_SUCCESS);
2749 }
2750 
2751 /*@
2752    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2753 
2754    Neighbor-wise Collective
2755 
2756    Input Parameters:
2757 +  mat - the matrix
2758 .  v1 - the vector to be multiplied by the transpose of the matrix
2759 -  v2 - the vector to be added to the result
2760 
2761    Output Parameter:
2762 .  v3 - the result
2763 
2764    Level: beginner
2765 
2766    Note:
2767    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2768    call `MatMultTransposeAdd`(A,v1,v2,v1).
2769 
2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2771 @*/
2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2773 {
2774   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2775 
2776   PetscFunctionBegin;
2777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2778   PetscValidType(mat, 1);
2779   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2780   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2781   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2782 
2783   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2784   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2785   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2786   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2787   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2788   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2789   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2790   MatCheckPreallocated(mat, 1);
2791 
2792   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2793   PetscCall(VecLockReadPush(v1));
2794   PetscCall((*op)(mat, v1, v2, v3));
2795   PetscCall(VecLockReadPop(v1));
2796   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2797   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2798   PetscFunctionReturn(PETSC_SUCCESS);
2799 }
2800 
2801 /*@
2802    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2803 
2804    Neighbor-wise Collective
2805 
2806    Input Parameters:
2807 +  mat - the matrix
2808 .  v1 - the vector to be multiplied by the Hermitian transpose
2809 -  v2 - the vector to be added to the result
2810 
2811    Output Parameter:
2812 .  v3 - the result
2813 
2814    Level: beginner
2815 
2816    Note:
2817    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2818    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2819 
2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2821 @*/
2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2823 {
2824   PetscFunctionBegin;
2825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2826   PetscValidType(mat, 1);
2827   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2828   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2829   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2830 
2831   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2832   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2833   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2834   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2835   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2836   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2837   MatCheckPreallocated(mat, 1);
2838 
2839   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2840   PetscCall(VecLockReadPush(v1));
2841   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2842   else {
2843     Vec w, z;
2844     PetscCall(VecDuplicate(v1, &w));
2845     PetscCall(VecCopy(v1, w));
2846     PetscCall(VecConjugate(w));
2847     PetscCall(VecDuplicate(v3, &z));
2848     PetscCall(MatMultTranspose(mat, w, z));
2849     PetscCall(VecDestroy(&w));
2850     PetscCall(VecConjugate(z));
2851     if (v2 != v3) {
2852       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2853     } else {
2854       PetscCall(VecAXPY(v3, 1.0, z));
2855     }
2856     PetscCall(VecDestroy(&z));
2857   }
2858   PetscCall(VecLockReadPop(v1));
2859   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2860   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2861   PetscFunctionReturn(PETSC_SUCCESS);
2862 }
2863 
2864 /*@C
2865    MatGetFactorType - gets the type of factorization it is
2866 
2867    Not Collective
2868 
2869    Input Parameter:
2870 .  mat - the matrix
2871 
2872    Output Parameter:
2873 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2874 
2875    Level: intermediate
2876 
2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2878           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2879 @*/
2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2881 {
2882   PetscFunctionBegin;
2883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2884   PetscValidType(mat, 1);
2885   PetscValidPointer(t, 2);
2886   *t = mat->factortype;
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@C
2891    MatSetFactorType - sets the type of factorization it is
2892 
2893    Logically Collective
2894 
2895    Input Parameters:
2896 +  mat - the matrix
2897 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2898 
2899    Level: intermediate
2900 
2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   mat->factortype = t;
2910   PetscFunctionReturn(PETSC_SUCCESS);
2911 }
2912 
2913 /*@C
2914    MatGetInfo - Returns information about matrix storage (number of
2915    nonzeros, memory, etc.).
2916 
2917    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2918 
2919    Input Parameters:
2920 +  mat - the matrix
2921 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2922 
2923    Output Parameter:
2924 .  info - matrix information context
2925 
2926    Options Database Key:
2927 .  -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2928 
2929    Notes:
2930    The `MatInfo` context contains a variety of matrix data, including
2931    number of nonzeros allocated and used, number of mallocs during
2932    matrix assembly, etc.  Additional information for factored matrices
2933    is provided (such as the fill ratio, number of mallocs during
2934    factorization, etc.).
2935 
2936    Example:
2937    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2938    data within the MatInfo context.  For example,
2939 .vb
2940       MatInfo info;
2941       Mat     A;
2942       double  mal, nz_a, nz_u;
2943 
2944       MatGetInfo(A, MAT_LOCAL, &info);
2945       mal  = info.mallocs;
2946       nz_a = info.nz_allocated;
2947 .ve
2948 
2949    Fortran users should declare info as a double precision
2950    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2951    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2952    a complete list of parameter names.
2953 .vb
2954       double  precision info(MAT_INFO_SIZE)
2955       double  precision mal, nz_a
2956       Mat     A
2957       integer ierr
2958 
2959       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2960       mal = info(MAT_INFO_MALLOCS)
2961       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2962 .ve
2963 
2964     Level: intermediate
2965 
2966     Developer Note:
2967     The Fortran interface is not autogenerated as the
2968     interface definition cannot be generated correctly [due to `MatInfo` argument]
2969 
2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2971 @*/
2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2973 {
2974   PetscFunctionBegin;
2975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2976   PetscValidType(mat, 1);
2977   PetscValidPointer(info, 3);
2978   MatCheckPreallocated(mat, 1);
2979   PetscUseTypeMethod(mat, getinfo, flag, info);
2980   PetscFunctionReturn(PETSC_SUCCESS);
2981 }
2982 
2983 /*
2984    This is used by external packages where it is not easy to get the info from the actual
2985    matrix factorization.
2986 */
2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2988 {
2989   PetscFunctionBegin;
2990   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2991   PetscFunctionReturn(PETSC_SUCCESS);
2992 }
2993 
2994 /*@C
2995    MatLUFactor - Performs in-place LU factorization of matrix.
2996 
2997    Collective
2998 
2999    Input Parameters:
3000 +  mat - the matrix
3001 .  row - row permutation
3002 .  col - column permutation
3003 -  info - options for factorization, includes
3004 .vb
3005           fill - expected fill as ratio of original fill.
3006           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3007                    Run with the option -info to determine an optimal value to use
3008 .ve
3009    Level: developer
3010 
3011    Notes:
3012    Most users should employ the `KSP` interface for linear solvers
3013    instead of working directly with matrix algebra routines such as this.
3014    See, e.g., `KSPCreate()`.
3015 
3016    This changes the state of the matrix to a factored matrix; it cannot be used
3017    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3018 
3019    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3020    when not using `KSP`.
3021 
3022    Developer Note:
3023    The Fortran interface is not autogenerated as the
3024    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3025 
3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3027           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3028 @*/
3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3030 {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3037   if (info) PetscValidPointer(info, 4);
3038   PetscValidType(mat, 1);
3039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3041   MatCheckPreallocated(mat, 1);
3042   if (!info) {
3043     PetscCall(MatFactorInfoInitialize(&tinfo));
3044     info = &tinfo;
3045   }
3046 
3047   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3048   PetscUseTypeMethod(mat, lufactor, row, col, info);
3049   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055    MatILUFactor - Performs in-place ILU factorization of matrix.
3056 
3057    Collective
3058 
3059    Input Parameters:
3060 +  mat - the matrix
3061 .  row - row permutation
3062 .  col - column permutation
3063 -  info - structure containing
3064 .vb
3065       levels - number of levels of fill.
3066       expected fill - as ratio of original fill.
3067       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3068                 missing diagonal entries)
3069 .ve
3070 
3071    Level: developer
3072 
3073    Notes:
3074    Most users should employ the `KSP` interface for linear solvers
3075    instead of working directly with matrix algebra routines such as this.
3076    See, e.g., `KSPCreate()`.
3077 
3078    Probably really in-place only when level of fill is zero, otherwise allocates
3079    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3080    when not using `KSP`.
3081 
3082    Developer Note:
3083    The Fortran interface is not autogenerated as the
3084    interface definition cannot be generated correctly [due to MatFactorInfo]
3085 
3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3087 @*/
3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3089 {
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3092   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3093   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3094   PetscValidPointer(info, 4);
3095   PetscValidType(mat, 1);
3096   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3099   MatCheckPreallocated(mat, 1);
3100 
3101   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3102   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3103   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3105   PetscFunctionReturn(PETSC_SUCCESS);
3106 }
3107 
3108 /*@C
3109    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3110    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3111 
3112    Collective
3113 
3114    Input Parameters:
3115 +  fact - the factor matrix obtained with `MatGetFactor()`
3116 .  mat - the matrix
3117 .  row - the row permutation
3118 .  col - the column permutation
3119 -  info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123 .ve
3124 
3125    Level: developer
3126 
3127    Notes:
3128     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3129 
3130    Most users should employ the simplified `KSP` interface for linear solvers
3131    instead of working directly with matrix algebra routines such as this.
3132    See, e.g., `KSPCreate()`.
3133 
3134    Developer Note:
3135    The Fortran interface is not autogenerated as the
3136    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137 
3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139 @*/
3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141 {
3142   MatFactorInfo tinfo;
3143 
3144   PetscFunctionBegin;
3145   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3147   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3148   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3149   if (info) PetscValidPointer(info, 5);
3150   PetscValidType(fact, 1);
3151   PetscValidType(mat, 2);
3152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3153   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3154   MatCheckPreallocated(mat, 2);
3155   if (!info) {
3156     PetscCall(MatFactorInfoInitialize(&tinfo));
3157     info = &tinfo;
3158   }
3159 
3160   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3161   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3162   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3163   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3164   PetscFunctionReturn(PETSC_SUCCESS);
3165 }
3166 
3167 /*@C
3168    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3169    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3170 
3171    Collective
3172 
3173    Input Parameters:
3174 +  fact - the factor matrix obtained with `MatGetFactor()`
3175 .  mat - the matrix
3176 -  info - options for factorization
3177 
3178    Level: developer
3179 
3180    Notes:
3181    See `MatLUFactor()` for in-place factorization.  See
3182    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3183 
3184    Most users should employ the `KSP` interface for linear solvers
3185    instead of working directly with matrix algebra routines such as this.
3186    See, e.g., `KSPCreate()`.
3187 
3188     Developer Note:
3189     The Fortran interface is not autogenerated as the
3190     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3191 
3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3193 @*/
3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3195 {
3196   MatFactorInfo tinfo;
3197 
3198   PetscFunctionBegin;
3199   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3201   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3202   PetscValidType(fact, 1);
3203   PetscValidType(mat, 2);
3204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3205   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3206              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3207 
3208   MatCheckPreallocated(mat, 2);
3209   if (!info) {
3210     PetscCall(MatFactorInfoInitialize(&tinfo));
3211     info = &tinfo;
3212   }
3213 
3214   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3215   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3216   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3217   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3218   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3219   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3220   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3221   PetscFunctionReturn(PETSC_SUCCESS);
3222 }
3223 
3224 /*@C
3225    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3226    symmetric matrix.
3227 
3228    Collective
3229 
3230    Input Parameters:
3231 +  mat - the matrix
3232 .  perm - row and column permutations
3233 -  f - expected fill as ratio of original fill
3234 
3235    Level: developer
3236 
3237    Notes:
3238    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3239    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3240 
3241    Most users should employ the `KSP` interface for linear solvers
3242    instead of working directly with matrix algebra routines such as this.
3243    See, e.g., `KSPCreate()`.
3244 
3245    Developer Note:
3246    The Fortran interface is not autogenerated as the
3247    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3248 
3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3250           `MatGetOrdering()`
3251 @*/
3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3253 {
3254   MatFactorInfo tinfo;
3255 
3256   PetscFunctionBegin;
3257   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3258   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3259   if (info) PetscValidPointer(info, 3);
3260   PetscValidType(mat, 1);
3261   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3262   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3263   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3264   MatCheckPreallocated(mat, 1);
3265   if (!info) {
3266     PetscCall(MatFactorInfoInitialize(&tinfo));
3267     info = &tinfo;
3268   }
3269 
3270   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3271   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3272   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3273   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3274   PetscFunctionReturn(PETSC_SUCCESS);
3275 }
3276 
3277 /*@C
3278    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3279    of a symmetric matrix.
3280 
3281    Collective
3282 
3283    Input Parameters:
3284 +  fact - the factor matrix obtained with `MatGetFactor()`
3285 .  mat - the matrix
3286 .  perm - row and column permutations
3287 -  info - options for factorization, includes
3288 .vb
3289           fill - expected fill as ratio of original fill.
3290           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3291                    Run with the option -info to determine an optimal value to use
3292 .ve
3293 
3294    Level: developer
3295 
3296    Notes:
3297    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3298    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3299 
3300    Most users should employ the `KSP` interface for linear solvers
3301    instead of working directly with matrix algebra routines such as this.
3302    See, e.g., `KSPCreate()`.
3303 
3304    Developer Note:
3305    The Fortran interface is not autogenerated as the
3306    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3307 
3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3309           `MatGetOrdering()`
3310 @*/
3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3312 {
3313   MatFactorInfo tinfo;
3314 
3315   PetscFunctionBegin;
3316   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3318   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3319   if (info) PetscValidPointer(info, 4);
3320   PetscValidType(fact, 1);
3321   PetscValidType(mat, 2);
3322   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3324   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3325   MatCheckPreallocated(mat, 2);
3326   if (!info) {
3327     PetscCall(MatFactorInfoInitialize(&tinfo));
3328     info = &tinfo;
3329   }
3330 
3331   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3332   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3333   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3334   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3335   PetscFunctionReturn(PETSC_SUCCESS);
3336 }
3337 
3338 /*@C
3339    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3340    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3341    `MatCholeskyFactorSymbolic()`.
3342 
3343    Collective
3344 
3345    Input Parameters:
3346 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3347 .  mat - the initial matrix that is to be factored
3348 -  info - options for factorization
3349 
3350    Level: developer
3351 
3352    Note:
3353    Most users should employ the `KSP` interface for linear solvers
3354    instead of working directly with matrix algebra routines such as this.
3355    See, e.g., `KSPCreate()`.
3356 
3357    Developer Note:
3358    The Fortran interface is not autogenerated as the
3359    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3360 
3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3362 @*/
3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3364 {
3365   MatFactorInfo tinfo;
3366 
3367   PetscFunctionBegin;
3368   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3370   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3371   PetscValidType(fact, 1);
3372   PetscValidType(mat, 2);
3373   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3374   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3375              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3376   MatCheckPreallocated(mat, 2);
3377   if (!info) {
3378     PetscCall(MatFactorInfoInitialize(&tinfo));
3379     info = &tinfo;
3380   }
3381 
3382   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3383   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3384   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3385   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3386   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3387   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3388   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3389   PetscFunctionReturn(PETSC_SUCCESS);
3390 }
3391 
3392 /*@
3393    MatQRFactor - Performs in-place QR factorization of matrix.
3394 
3395    Collective
3396 
3397    Input Parameters:
3398 +  mat - the matrix
3399 .  col - column permutation
3400 -  info - options for factorization, includes
3401 .vb
3402           fill - expected fill as ratio of original fill.
3403           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3404                    Run with the option -info to determine an optimal value to use
3405 .ve
3406 
3407    Level: developer
3408 
3409    Notes:
3410    Most users should employ the `KSP` interface for linear solvers
3411    instead of working directly with matrix algebra routines such as this.
3412    See, e.g., `KSPCreate()`.
3413 
3414    This changes the state of the matrix to a factored matrix; it cannot be used
3415    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3416 
3417    Developer Note:
3418    The Fortran interface is not autogenerated as the
3419    interface definition cannot be generated correctly [due to MatFactorInfo]
3420 
3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3422           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3423 @*/
3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3425 {
3426   PetscFunctionBegin;
3427   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3428   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3429   if (info) PetscValidPointer(info, 3);
3430   PetscValidType(mat, 1);
3431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3433   MatCheckPreallocated(mat, 1);
3434   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3435   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3436   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3437   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3438   PetscFunctionReturn(PETSC_SUCCESS);
3439 }
3440 
3441 /*@
3442    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3443    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3444 
3445    Collective
3446 
3447    Input Parameters:
3448 +  fact - the factor matrix obtained with `MatGetFactor()`
3449 .  mat - the matrix
3450 .  col - column permutation
3451 -  info - options for factorization, includes
3452 .vb
3453           fill - expected fill as ratio of original fill.
3454           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3455                    Run with the option -info to determine an optimal value to use
3456 .ve
3457 
3458    Level: developer
3459 
3460    Note:
3461    Most users should employ the `KSP` interface for linear solvers
3462    instead of working directly with matrix algebra routines such as this.
3463    See, e.g., `KSPCreate()`.
3464 
3465    Developer Note:
3466    The Fortran interface is not autogenerated as the
3467    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3468 
3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3470 @*/
3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3472 {
3473   MatFactorInfo tinfo;
3474 
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3478   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3479   if (info) PetscValidPointer(info, 4);
3480   PetscValidType(fact, 1);
3481   PetscValidType(mat, 2);
3482   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3483   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3484   MatCheckPreallocated(mat, 2);
3485   if (!info) {
3486     PetscCall(MatFactorInfoInitialize(&tinfo));
3487     info = &tinfo;
3488   }
3489 
3490   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3491   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3492   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3493   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3494   PetscFunctionReturn(PETSC_SUCCESS);
3495 }
3496 
3497 /*@
3498    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3499    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3500 
3501    Collective
3502 
3503    Input Parameters:
3504 +  fact - the factor matrix obtained with `MatGetFactor()`
3505 .  mat - the matrix
3506 -  info - options for factorization
3507 
3508    Level: developer
3509 
3510    Notes:
3511    See `MatQRFactor()` for in-place factorization.
3512 
3513    Most users should employ the `KSP` interface for linear solvers
3514    instead of working directly with matrix algebra routines such as this.
3515    See, e.g., `KSPCreate()`.
3516 
3517    Developer Note:
3518    The Fortran interface is not autogenerated as the
3519    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3520 
3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3522 @*/
3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3524 {
3525   MatFactorInfo tinfo;
3526 
3527   PetscFunctionBegin;
3528   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3530   PetscValidType(fact, 1);
3531   PetscValidType(mat, 2);
3532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3533   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3534              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3535 
3536   MatCheckPreallocated(mat, 2);
3537   if (!info) {
3538     PetscCall(MatFactorInfoInitialize(&tinfo));
3539     info = &tinfo;
3540   }
3541 
3542   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3543   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3544   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3545   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3546   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3547   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3548   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3549   PetscFunctionReturn(PETSC_SUCCESS);
3550 }
3551 
3552 /*@
3553    MatSolve - Solves A x = b, given a factored matrix.
3554 
3555    Neighbor-wise Collective
3556 
3557    Input Parameters:
3558 +  mat - the factored matrix
3559 -  b - the right-hand-side vector
3560 
3561    Output Parameter:
3562 .  x - the result vector
3563 
3564    Level: developer
3565 
3566    Notes:
3567    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3568    call `MatSolve`(A,x,x).
3569 
3570    Most users should employ the `KSP` interface for linear solvers
3571    instead of working directly with matrix algebra routines such as this.
3572    See, e.g., `KSPCreate()`.
3573 
3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3575 @*/
3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3577 {
3578   PetscFunctionBegin;
3579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3580   PetscValidType(mat, 1);
3581   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3582   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3583   PetscCheckSameComm(mat, 1, b, 2);
3584   PetscCheckSameComm(mat, 1, x, 3);
3585   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3586   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3587   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3588   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3589   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3590   MatCheckPreallocated(mat, 1);
3591 
3592   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3593   if (mat->factorerrortype) {
3594     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3595     PetscCall(VecSetInf(x));
3596   } else PetscUseTypeMethod(mat, solve, b, x);
3597   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3598   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3599   PetscFunctionReturn(PETSC_SUCCESS);
3600 }
3601 
3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3603 {
3604   Vec      b, x;
3605   PetscInt N, i;
3606   PetscErrorCode (*f)(Mat, Vec, Vec);
3607   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3608 
3609   PetscFunctionBegin;
3610   if (A->factorerrortype) {
3611     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3612     PetscCall(MatSetInf(X));
3613     PetscFunctionReturn(PETSC_SUCCESS);
3614   }
3615   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3616   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3617   PetscCall(MatBoundToCPU(A, &Abound));
3618   if (!Abound) {
3619     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3620     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3621   }
3622 #if PetscDefined(HAVE_CUDA)
3623   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3624   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3625 #elif PetscDefined(HAVE_HIP)
3626   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3627   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3628 #endif
3629   PetscCall(MatGetSize(B, NULL, &N));
3630   for (i = 0; i < N; i++) {
3631     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3632     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3633     PetscCall((*f)(A, b, x));
3634     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3635     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3636   }
3637   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3638   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3639   PetscFunctionReturn(PETSC_SUCCESS);
3640 }
3641 
3642 /*@
3643    MatMatSolve - Solves A X = B, given a factored matrix.
3644 
3645    Neighbor-wise Collective
3646 
3647    Input Parameters:
3648 +  A - the factored matrix
3649 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3650 
3651    Output Parameter:
3652 .  X - the result matrix (dense matrix)
3653 
3654    Level: developer
3655 
3656    Note:
3657    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3658    otherwise, `B` and `X` cannot be the same.
3659 
3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3661 @*/
3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3663 {
3664   PetscFunctionBegin;
3665   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3666   PetscValidType(A, 1);
3667   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3668   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3669   PetscCheckSameComm(A, 1, B, 2);
3670   PetscCheckSameComm(A, 1, X, 3);
3671   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3672   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3673   PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3674   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3675   MatCheckPreallocated(A, 1);
3676 
3677   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3678   if (!A->ops->matsolve) {
3679     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3680     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3681   } else PetscUseTypeMethod(A, matsolve, B, X);
3682   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3683   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3684   PetscFunctionReturn(PETSC_SUCCESS);
3685 }
3686 
3687 /*@
3688    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3689 
3690    Neighbor-wise Collective
3691 
3692    Input Parameters:
3693 +  A - the factored matrix
3694 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3695 
3696    Output Parameter:
3697 .  X - the result matrix (dense matrix)
3698 
3699    Level: developer
3700 
3701    Note:
3702    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3703    call `MatMatSolveTranspose`(A,X,X).
3704 
3705 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3706 @*/
3707 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3708 {
3709   PetscFunctionBegin;
3710   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3711   PetscValidType(A, 1);
3712   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3713   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3714   PetscCheckSameComm(A, 1, B, 2);
3715   PetscCheckSameComm(A, 1, X, 3);
3716   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3717   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3718   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3719   PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n);
3720   PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3721   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3722   MatCheckPreallocated(A, 1);
3723 
3724   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3725   if (!A->ops->matsolvetranspose) {
3726     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3727     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3728   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3729   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3730   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3731   PetscFunctionReturn(PETSC_SUCCESS);
3732 }
3733 
3734 /*@
3735    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3736 
3737    Neighbor-wise Collective
3738 
3739    Input Parameters:
3740 +  A - the factored matrix
3741 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3742 
3743    Output Parameter:
3744 .  X - the result matrix (dense matrix)
3745 
3746    Level: developer
3747 
3748    Note:
3749    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
3750    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3751 
3752 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3753 @*/
3754 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3755 {
3756   PetscFunctionBegin;
3757   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3758   PetscValidType(A, 1);
3759   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3760   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3761   PetscCheckSameComm(A, 1, Bt, 2);
3762   PetscCheckSameComm(A, 1, X, 3);
3763 
3764   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3765   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);
3766   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);
3767   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");
3768   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3769   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3770   MatCheckPreallocated(A, 1);
3771 
3772   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3773   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3774   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3775   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3776   PetscFunctionReturn(PETSC_SUCCESS);
3777 }
3778 
3779 /*@
3780    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3781                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3782 
3783    Neighbor-wise Collective
3784 
3785    Input Parameters:
3786 +  mat - the factored matrix
3787 -  b - the right-hand-side vector
3788 
3789    Output Parameter:
3790 .  x - the result vector
3791 
3792    Level: developer
3793 
3794    Notes:
3795    `MatSolve()` should be used for most applications, as it performs
3796    a forward solve followed by a backward solve.
3797 
3798    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3799    call `MatForwardSolve`(A,x,x).
3800 
3801    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3802    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3803    `MatForwardSolve()` solves U^T*D y = b, and
3804    `MatBackwardSolve()` solves U x = y.
3805    Thus they do not provide a symmetric preconditioner.
3806 
3807 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3808 @*/
3809 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3810 {
3811   PetscFunctionBegin;
3812   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3813   PetscValidType(mat, 1);
3814   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3815   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3816   PetscCheckSameComm(mat, 1, b, 2);
3817   PetscCheckSameComm(mat, 1, x, 3);
3818   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3819   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);
3820   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);
3821   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);
3822   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3823   MatCheckPreallocated(mat, 1);
3824 
3825   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3826   PetscUseTypeMethod(mat, forwardsolve, b, x);
3827   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3828   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3829   PetscFunctionReturn(PETSC_SUCCESS);
3830 }
3831 
3832 /*@
3833    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3834                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3835 
3836    Neighbor-wise Collective
3837 
3838    Input Parameters:
3839 +  mat - the factored matrix
3840 -  b - the right-hand-side vector
3841 
3842    Output Parameter:
3843 .  x - the result vector
3844 
3845    Level: developer
3846 
3847    Notes:
3848    `MatSolve()` should be used for most applications, as it performs
3849    a forward solve followed by a backward solve.
3850 
3851    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3852    call `MatBackwardSolve`(A,x,x).
3853 
3854    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3855    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3856    `MatForwardSolve()` solves U^T*D y = b, and
3857    `MatBackwardSolve()` solves U x = y.
3858    Thus they do not provide a symmetric preconditioner.
3859 
3860 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3861 @*/
3862 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3863 {
3864   PetscFunctionBegin;
3865   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3866   PetscValidType(mat, 1);
3867   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3868   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3869   PetscCheckSameComm(mat, 1, b, 2);
3870   PetscCheckSameComm(mat, 1, x, 3);
3871   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3872   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);
3873   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);
3874   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);
3875   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3876   MatCheckPreallocated(mat, 1);
3877 
3878   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3879   PetscUseTypeMethod(mat, backwardsolve, b, x);
3880   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3881   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3882   PetscFunctionReturn(PETSC_SUCCESS);
3883 }
3884 
3885 /*@
3886    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3887 
3888    Neighbor-wise Collective
3889 
3890    Input Parameters:
3891 +  mat - the factored matrix
3892 .  b - the right-hand-side vector
3893 -  y - the vector to be added to
3894 
3895    Output Parameter:
3896 .  x - the result vector
3897 
3898    Level: developer
3899 
3900    Note:
3901    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3902    call `MatSolveAdd`(A,x,y,x).
3903 
3904 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3905 @*/
3906 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3907 {
3908   PetscScalar one = 1.0;
3909   Vec         tmp;
3910 
3911   PetscFunctionBegin;
3912   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3913   PetscValidType(mat, 1);
3914   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3915   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3916   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3917   PetscCheckSameComm(mat, 1, b, 2);
3918   PetscCheckSameComm(mat, 1, y, 3);
3919   PetscCheckSameComm(mat, 1, x, 4);
3920   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3921   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);
3922   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);
3923   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);
3924   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);
3925   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);
3926   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3927   MatCheckPreallocated(mat, 1);
3928 
3929   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3930   if (mat->factorerrortype) {
3931     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3932     PetscCall(VecSetInf(x));
3933   } else if (mat->ops->solveadd) {
3934     PetscUseTypeMethod(mat, solveadd, b, y, x);
3935   } else {
3936     /* do the solve then the add manually */
3937     if (x != y) {
3938       PetscCall(MatSolve(mat, b, x));
3939       PetscCall(VecAXPY(x, one, y));
3940     } else {
3941       PetscCall(VecDuplicate(x, &tmp));
3942       PetscCall(VecCopy(x, tmp));
3943       PetscCall(MatSolve(mat, b, x));
3944       PetscCall(VecAXPY(x, one, tmp));
3945       PetscCall(VecDestroy(&tmp));
3946     }
3947   }
3948   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3949   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3950   PetscFunctionReturn(PETSC_SUCCESS);
3951 }
3952 
3953 /*@
3954    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3955 
3956    Neighbor-wise Collective
3957 
3958    Input Parameters:
3959 +  mat - the factored matrix
3960 -  b - the right-hand-side vector
3961 
3962    Output Parameter:
3963 .  x - the result vector
3964 
3965    Level: developer
3966 
3967    Notes:
3968    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3969    call `MatSolveTranspose`(A,x,x).
3970 
3971    Most users should employ the `KSP` interface for linear solvers
3972    instead of working directly with matrix algebra routines such as this.
3973    See, e.g., `KSPCreate()`.
3974 
3975 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3976 @*/
3977 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3978 {
3979   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3980 
3981   PetscFunctionBegin;
3982   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3983   PetscValidType(mat, 1);
3984   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3985   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3986   PetscCheckSameComm(mat, 1, b, 2);
3987   PetscCheckSameComm(mat, 1, x, 3);
3988   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3989   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);
3990   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);
3991   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3992   MatCheckPreallocated(mat, 1);
3993   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3994   if (mat->factorerrortype) {
3995     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3996     PetscCall(VecSetInf(x));
3997   } else {
3998     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
3999     PetscCall((*f)(mat, b, x));
4000   }
4001   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4002   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4003   PetscFunctionReturn(PETSC_SUCCESS);
4004 }
4005 
4006 /*@
4007    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4008                       factored matrix.
4009 
4010    Neighbor-wise Collective
4011 
4012    Input Parameters:
4013 +  mat - the factored matrix
4014 .  b - the right-hand-side vector
4015 -  y - the vector to be added to
4016 
4017    Output Parameter:
4018 .  x - the result vector
4019 
4020    Level: developer
4021 
4022    Note:
4023    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4024    call `MatSolveTransposeAdd`(A,x,y,x).
4025 
4026 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4027 @*/
4028 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4029 {
4030   PetscScalar one = 1.0;
4031   Vec         tmp;
4032   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4033 
4034   PetscFunctionBegin;
4035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4036   PetscValidType(mat, 1);
4037   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4038   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4039   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4040   PetscCheckSameComm(mat, 1, b, 2);
4041   PetscCheckSameComm(mat, 1, y, 3);
4042   PetscCheckSameComm(mat, 1, x, 4);
4043   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4044   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);
4045   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);
4046   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);
4047   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);
4048   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4049   MatCheckPreallocated(mat, 1);
4050 
4051   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4052   if (mat->factorerrortype) {
4053     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4054     PetscCall(VecSetInf(x));
4055   } else if (f) {
4056     PetscCall((*f)(mat, b, y, x));
4057   } else {
4058     /* do the solve then the add manually */
4059     if (x != y) {
4060       PetscCall(MatSolveTranspose(mat, b, x));
4061       PetscCall(VecAXPY(x, one, y));
4062     } else {
4063       PetscCall(VecDuplicate(x, &tmp));
4064       PetscCall(VecCopy(x, tmp));
4065       PetscCall(MatSolveTranspose(mat, b, x));
4066       PetscCall(VecAXPY(x, one, tmp));
4067       PetscCall(VecDestroy(&tmp));
4068     }
4069   }
4070   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4071   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4072   PetscFunctionReturn(PETSC_SUCCESS);
4073 }
4074 
4075 /*@
4076    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4077 
4078    Neighbor-wise Collective
4079 
4080    Input Parameters:
4081 +  mat - the matrix
4082 .  b - the right hand side
4083 .  omega - the relaxation factor
4084 .  flag - flag indicating the type of SOR (see below)
4085 .  shift -  diagonal shift
4086 .  its - the number of iterations
4087 -  lits - the number of local iterations
4088 
4089    Output Parameter:
4090 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4091 
4092    SOR Flags:
4093 +     `SOR_FORWARD_SWEEP` - forward SOR
4094 .     `SOR_BACKWARD_SWEEP` - backward SOR
4095 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4096 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4097 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4098 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4099 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4100 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4101          upper/lower triangular part of matrix to
4102          vector (with omega)
4103 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4104 
4105    Level: developer
4106 
4107    Notes:
4108    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4109    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4110    on each processor.
4111 
4112    Application programmers will not generally use `MatSOR()` directly,
4113    but instead will employ the `KSP`/`PC` interface.
4114 
4115    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4116 
4117    Most users should employ the `KSP` interface for linear solvers
4118    instead of working directly with matrix algebra routines such as this.
4119    See, e.g., `KSPCreate()`.
4120 
4121    Vectors `x` and `b` CANNOT be the same
4122 
4123    The flags are implemented as bitwise inclusive or operations.
4124    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4125    to specify a zero initial guess for SSOR.
4126 
4127    Developer Note:
4128    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4129 
4130 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4131 @*/
4132 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4133 {
4134   PetscFunctionBegin;
4135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4136   PetscValidType(mat, 1);
4137   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4138   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4139   PetscCheckSameComm(mat, 1, b, 2);
4140   PetscCheckSameComm(mat, 1, x, 8);
4141   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4142   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4143   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);
4144   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);
4145   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);
4146   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4147   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4148   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4149 
4150   MatCheckPreallocated(mat, 1);
4151   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4152   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4153   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4154   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4155   PetscFunctionReturn(PETSC_SUCCESS);
4156 }
4157 
4158 /*
4159       Default matrix copy routine.
4160 */
4161 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4162 {
4163   PetscInt           i, rstart = 0, rend = 0, nz;
4164   const PetscInt    *cwork;
4165   const PetscScalar *vwork;
4166 
4167   PetscFunctionBegin;
4168   if (B->assembled) PetscCall(MatZeroEntries(B));
4169   if (str == SAME_NONZERO_PATTERN) {
4170     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4171     for (i = rstart; i < rend; i++) {
4172       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4173       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4174       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4175     }
4176   } else {
4177     PetscCall(MatAYPX(B, 0.0, A, str));
4178   }
4179   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4180   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4181   PetscFunctionReturn(PETSC_SUCCESS);
4182 }
4183 
4184 /*@
4185    MatCopy - Copies a matrix to another matrix.
4186 
4187    Collective
4188 
4189    Input Parameters:
4190 +  A - the matrix
4191 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4192 
4193    Output Parameter:
4194 .  B - where the copy is put
4195 
4196    Level: intermediate
4197 
4198    Notes:
4199    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4200 
4201    `MatCopy()` copies the matrix entries of a matrix to another existing
4202    matrix (after first zeroing the second matrix).  A related routine is
4203    `MatConvert()`, which first creates a new matrix and then copies the data.
4204 
4205 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4206 @*/
4207 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4208 {
4209   PetscInt i;
4210 
4211   PetscFunctionBegin;
4212   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4213   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4214   PetscValidType(A, 1);
4215   PetscValidType(B, 2);
4216   PetscCheckSameComm(A, 1, B, 2);
4217   MatCheckPreallocated(B, 2);
4218   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4219   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4220   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,
4221              A->cmap->N, B->cmap->N);
4222   MatCheckPreallocated(A, 1);
4223   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4224 
4225   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4226   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4227   else PetscCall(MatCopy_Basic(A, B, str));
4228 
4229   B->stencil.dim = A->stencil.dim;
4230   B->stencil.noc = A->stencil.noc;
4231   for (i = 0; i <= A->stencil.dim; i++) {
4232     B->stencil.dims[i]   = A->stencil.dims[i];
4233     B->stencil.starts[i] = A->stencil.starts[i];
4234   }
4235 
4236   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4237   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4238   PetscFunctionReturn(PETSC_SUCCESS);
4239 }
4240 
4241 /*@C
4242    MatConvert - Converts a matrix to another matrix, either of the same
4243    or different type.
4244 
4245    Collective
4246 
4247    Input Parameters:
4248 +  mat - the matrix
4249 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4250    same type as the original matrix.
4251 -  reuse - denotes if the destination matrix is to be created or reused.
4252    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
4253    `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).
4254 
4255    Output Parameter:
4256 .  M - pointer to place new matrix
4257 
4258    Level: intermediate
4259 
4260    Notes:
4261    `MatConvert()` first creates a new matrix and then copies the data from
4262    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4263    entries of one matrix to another already existing matrix context.
4264 
4265    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4266    the MPI communicator of the generated matrix is always the same as the communicator
4267    of the input matrix.
4268 
4269 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4270 @*/
4271 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4272 {
4273   PetscBool  sametype, issame, flg;
4274   PetscBool3 issymmetric, ishermitian;
4275   char       convname[256], mtype[256];
4276   Mat        B;
4277 
4278   PetscFunctionBegin;
4279   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4280   PetscValidType(mat, 1);
4281   PetscValidPointer(M, 4);
4282   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4283   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4284   MatCheckPreallocated(mat, 1);
4285 
4286   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4287   if (flg) newtype = mtype;
4288 
4289   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4290   PetscCall(PetscStrcmp(newtype, "same", &issame));
4291   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4292   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");
4293 
4294   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4295     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4296     PetscFunctionReturn(PETSC_SUCCESS);
4297   }
4298 
4299   /* Cache Mat options because some converters use MatHeaderReplace  */
4300   issymmetric = mat->symmetric;
4301   ishermitian = mat->hermitian;
4302 
4303   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4304     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4305     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4306   } else {
4307     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4308     const char *prefix[3]                                 = {"seq", "mpi", ""};
4309     PetscInt    i;
4310     /*
4311        Order of precedence:
4312        0) See if newtype is a superclass of the current matrix.
4313        1) See if a specialized converter is known to the current matrix.
4314        2) See if a specialized converter is known to the desired matrix class.
4315        3) See if a good general converter is registered for the desired class
4316           (as of 6/27/03 only MATMPIADJ falls into this category).
4317        4) See if a good general converter is known for the current matrix.
4318        5) Use a really basic converter.
4319     */
4320 
4321     /* 0) See if newtype is a superclass of the current matrix.
4322           i.e mat is mpiaij and newtype is aij */
4323     for (i = 0; i < 2; i++) {
4324       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4325       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4326       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4327       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4328       if (flg) {
4329         if (reuse == MAT_INPLACE_MATRIX) {
4330           PetscCall(PetscInfo(mat, "Early return\n"));
4331           PetscFunctionReturn(PETSC_SUCCESS);
4332         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4333           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4334           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4335           PetscFunctionReturn(PETSC_SUCCESS);
4336         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4337           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4338           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4339           PetscFunctionReturn(PETSC_SUCCESS);
4340         }
4341       }
4342     }
4343     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4344     for (i = 0; i < 3; i++) {
4345       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4346       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4347       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4348       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4351       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4352       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4353       if (conv) goto foundconv;
4354     }
4355 
4356     /* 2)  See if a specialized converter is known to the desired matrix class. */
4357     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4358     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4359     PetscCall(MatSetType(B, newtype));
4360     for (i = 0; i < 3; i++) {
4361       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4367       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4368       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4369       if (conv) {
4370         PetscCall(MatDestroy(&B));
4371         goto foundconv;
4372       }
4373     }
4374 
4375     /* 3) See if a good general converter is registered for the desired class */
4376     conv = B->ops->convertfrom;
4377     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4378     PetscCall(MatDestroy(&B));
4379     if (conv) goto foundconv;
4380 
4381     /* 4) See if a good general converter is known for the current matrix */
4382     if (mat->ops->convert) conv = mat->ops->convert;
4383     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4384     if (conv) goto foundconv;
4385 
4386     /* 5) Use a really basic converter. */
4387     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4388     conv = MatConvert_Basic;
4389 
4390   foundconv:
4391     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4392     PetscCall((*conv)(mat, newtype, reuse, M));
4393     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4394       /* the block sizes must be same if the mappings are copied over */
4395       (*M)->rmap->bs = mat->rmap->bs;
4396       (*M)->cmap->bs = mat->cmap->bs;
4397       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4398       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4399       (*M)->rmap->mapping = mat->rmap->mapping;
4400       (*M)->cmap->mapping = mat->cmap->mapping;
4401     }
4402     (*M)->stencil.dim = mat->stencil.dim;
4403     (*M)->stencil.noc = mat->stencil.noc;
4404     for (i = 0; i <= mat->stencil.dim; i++) {
4405       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4406       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4407     }
4408     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4409   }
4410   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4411 
4412   /* Copy Mat options */
4413   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4414   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4415   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4416   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4417   PetscFunctionReturn(PETSC_SUCCESS);
4418 }
4419 
4420 /*@C
4421    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4422 
4423    Not Collective
4424 
4425    Input Parameter:
4426 .  mat - the matrix, must be a factored matrix
4427 
4428    Output Parameter:
4429 .   type - the string name of the package (do not free this string)
4430 
4431    Level: intermediate
4432 
4433    Fortran Note:
4434    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4435 
4436 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4437 @*/
4438 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4439 {
4440   PetscErrorCode (*conv)(Mat, MatSolverType *);
4441 
4442   PetscFunctionBegin;
4443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4444   PetscValidType(mat, 1);
4445   PetscValidPointer(type, 2);
4446   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4447   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4448   if (conv) PetscCall((*conv)(mat, type));
4449   else *type = MATSOLVERPETSC;
4450   PetscFunctionReturn(PETSC_SUCCESS);
4451 }
4452 
4453 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4454 struct _MatSolverTypeForSpecifcType {
4455   MatType mtype;
4456   /* no entry for MAT_FACTOR_NONE */
4457   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4458   MatSolverTypeForSpecifcType next;
4459 };
4460 
4461 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4462 struct _MatSolverTypeHolder {
4463   char                       *name;
4464   MatSolverTypeForSpecifcType handlers;
4465   MatSolverTypeHolder         next;
4466 };
4467 
4468 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4469 
4470 /*@C
4471    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4472 
4473    Input Parameters:
4474 +    package - name of the package, for example petsc or superlu
4475 .    mtype - the matrix type that works with this package
4476 .    ftype - the type of factorization supported by the package
4477 -    createfactor - routine that will create the factored matrix ready to be used
4478 
4479     Level: developer
4480 
4481 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4482 @*/
4483 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4484 {
4485   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4486   PetscBool                   flg;
4487   MatSolverTypeForSpecifcType inext, iprev = NULL;
4488 
4489   PetscFunctionBegin;
4490   PetscCall(MatInitializePackage());
4491   if (!next) {
4492     PetscCall(PetscNew(&MatSolverTypeHolders));
4493     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4494     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4495     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4496     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4497     PetscFunctionReturn(PETSC_SUCCESS);
4498   }
4499   while (next) {
4500     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4501     if (flg) {
4502       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4503       inext = next->handlers;
4504       while (inext) {
4505         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4506         if (flg) {
4507           inext->createfactor[(int)ftype - 1] = createfactor;
4508           PetscFunctionReturn(PETSC_SUCCESS);
4509         }
4510         iprev = inext;
4511         inext = inext->next;
4512       }
4513       PetscCall(PetscNew(&iprev->next));
4514       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4515       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4516       PetscFunctionReturn(PETSC_SUCCESS);
4517     }
4518     prev = next;
4519     next = next->next;
4520   }
4521   PetscCall(PetscNew(&prev->next));
4522   PetscCall(PetscStrallocpy(package, &prev->next->name));
4523   PetscCall(PetscNew(&prev->next->handlers));
4524   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4525   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4526   PetscFunctionReturn(PETSC_SUCCESS);
4527 }
4528 
4529 /*@C
4530    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4531 
4532    Input Parameters:
4533 +    type - name of the package, for example petsc or superlu
4534 .    ftype - the type of factorization supported by the type
4535 -    mtype - the matrix type that works with this type
4536 
4537    Output Parameters:
4538 +   foundtype - `PETSC_TRUE` if the type was registered
4539 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4540 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4541 
4542     Level: developer
4543 
4544 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4545 @*/
4546 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4547 {
4548   MatSolverTypeHolder         next = MatSolverTypeHolders;
4549   PetscBool                   flg;
4550   MatSolverTypeForSpecifcType inext;
4551 
4552   PetscFunctionBegin;
4553   if (foundtype) *foundtype = PETSC_FALSE;
4554   if (foundmtype) *foundmtype = PETSC_FALSE;
4555   if (createfactor) *createfactor = NULL;
4556 
4557   if (type) {
4558     while (next) {
4559       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4560       if (flg) {
4561         if (foundtype) *foundtype = PETSC_TRUE;
4562         inext = next->handlers;
4563         while (inext) {
4564           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4565           if (flg) {
4566             if (foundmtype) *foundmtype = PETSC_TRUE;
4567             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4568             PetscFunctionReturn(PETSC_SUCCESS);
4569           }
4570           inext = inext->next;
4571         }
4572       }
4573       next = next->next;
4574     }
4575   } else {
4576     while (next) {
4577       inext = next->handlers;
4578       while (inext) {
4579         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4580         if (flg && inext->createfactor[(int)ftype - 1]) {
4581           if (foundtype) *foundtype = PETSC_TRUE;
4582           if (foundmtype) *foundmtype = PETSC_TRUE;
4583           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4584           PetscFunctionReturn(PETSC_SUCCESS);
4585         }
4586         inext = inext->next;
4587       }
4588       next = next->next;
4589     }
4590     /* try with base classes inext->mtype */
4591     next = MatSolverTypeHolders;
4592     while (next) {
4593       inext = next->handlers;
4594       while (inext) {
4595         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4596         if (flg && inext->createfactor[(int)ftype - 1]) {
4597           if (foundtype) *foundtype = PETSC_TRUE;
4598           if (foundmtype) *foundmtype = PETSC_TRUE;
4599           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4600           PetscFunctionReturn(PETSC_SUCCESS);
4601         }
4602         inext = inext->next;
4603       }
4604       next = next->next;
4605     }
4606   }
4607   PetscFunctionReturn(PETSC_SUCCESS);
4608 }
4609 
4610 PetscErrorCode MatSolverTypeDestroy(void)
4611 {
4612   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4613   MatSolverTypeForSpecifcType inext, iprev;
4614 
4615   PetscFunctionBegin;
4616   while (next) {
4617     PetscCall(PetscFree(next->name));
4618     inext = next->handlers;
4619     while (inext) {
4620       PetscCall(PetscFree(inext->mtype));
4621       iprev = inext;
4622       inext = inext->next;
4623       PetscCall(PetscFree(iprev));
4624     }
4625     prev = next;
4626     next = next->next;
4627     PetscCall(PetscFree(prev));
4628   }
4629   MatSolverTypeHolders = NULL;
4630   PetscFunctionReturn(PETSC_SUCCESS);
4631 }
4632 
4633 /*@C
4634    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4635 
4636    Logically Collective
4637 
4638    Input Parameter:
4639 .  mat - the matrix
4640 
4641    Output Parameter:
4642 .  flg - `PETSC_TRUE` if uses the ordering
4643 
4644    Level: developer
4645 
4646    Note:
4647    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4648    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4649 
4650 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4651 @*/
4652 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4653 {
4654   PetscFunctionBegin;
4655   *flg = mat->canuseordering;
4656   PetscFunctionReturn(PETSC_SUCCESS);
4657 }
4658 
4659 /*@C
4660    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4661 
4662    Logically Collective
4663 
4664    Input Parameters:
4665 +  mat - the matrix obtained with `MatGetFactor()`
4666 -  ftype - the factorization type to be used
4667 
4668    Output Parameter:
4669 .  otype - the preferred ordering type
4670 
4671    Level: developer
4672 
4673 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4674 @*/
4675 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4676 {
4677   PetscFunctionBegin;
4678   *otype = mat->preferredordering[ftype];
4679   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4680   PetscFunctionReturn(PETSC_SUCCESS);
4681 }
4682 
4683 /*@C
4684    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4685 
4686    Collective
4687 
4688    Input Parameters:
4689 +  mat - the matrix
4690 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4691 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4692 
4693    Output Parameter:
4694 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4695 
4696    Options Database Key:
4697 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4698                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4699 
4700    Level: intermediate
4701 
4702    Notes:
4703      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4704      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4705 
4706      Users usually access the factorization solvers via `KSP`
4707 
4708       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4709      such as pastix, superlu, mumps etc.
4710 
4711       PETSc must have been ./configure to use the external solver, using the option --download-package
4712 
4713       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4714       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4715       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4716 
4717    Developer Note:
4718       This should actually be called `MatCreateFactor()` since it creates a new factor object
4719 
4720 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4721           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4722 @*/
4723 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4724 {
4725   PetscBool foundtype, foundmtype;
4726   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4727 
4728   PetscFunctionBegin;
4729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4730   PetscValidType(mat, 1);
4731 
4732   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4733   MatCheckPreallocated(mat, 1);
4734 
4735   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4736   if (!foundtype) {
4737     if (type) {
4738       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],
4739               ((PetscObject)mat)->type_name, type);
4740     } else {
4741       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);
4742     }
4743   }
4744   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4745   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);
4746 
4747   PetscCall((*conv)(mat, ftype, f));
4748   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4749   PetscFunctionReturn(PETSC_SUCCESS);
4750 }
4751 
4752 /*@C
4753    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4754 
4755    Not Collective
4756 
4757    Input Parameters:
4758 +  mat - the matrix
4759 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4760 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4761 
4762    Output Parameter:
4763 .    flg - PETSC_TRUE if the factorization is available
4764 
4765    Level: intermediate
4766 
4767    Notes:
4768       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4769      such as pastix, superlu, mumps etc.
4770 
4771       PETSc must have been ./configure to use the external solver, using the option --download-package
4772 
4773    Developer Note:
4774       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4775 
4776 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4777           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4778 @*/
4779 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4780 {
4781   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4782 
4783   PetscFunctionBegin;
4784   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4785   PetscValidType(mat, 1);
4786   PetscValidBoolPointer(flg, 4);
4787 
4788   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4789   MatCheckPreallocated(mat, 1);
4790 
4791   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4792   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4793   PetscFunctionReturn(PETSC_SUCCESS);
4794 }
4795 
4796 /*@
4797    MatDuplicate - Duplicates a matrix including the non-zero structure.
4798 
4799    Collective
4800 
4801    Input Parameters:
4802 +  mat - the matrix
4803 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4804         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4805 
4806    Output Parameter:
4807 .  M - pointer to place new matrix
4808 
4809    Level: intermediate
4810 
4811    Notes:
4812     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4813 
4814     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.
4815 
4816     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
4817     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4818     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4819 
4820 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4821 @*/
4822 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4823 {
4824   Mat         B;
4825   VecType     vtype;
4826   PetscInt    i;
4827   PetscObject dm, container_h, container_d;
4828   void (*viewf)(void);
4829 
4830   PetscFunctionBegin;
4831   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4832   PetscValidType(mat, 1);
4833   PetscValidPointer(M, 3);
4834   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4835   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4836   MatCheckPreallocated(mat, 1);
4837 
4838   *M = NULL;
4839   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4840   PetscUseTypeMethod(mat, duplicate, op, M);
4841   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4842   B = *M;
4843 
4844   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4845   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4846   PetscCall(MatGetVecType(mat, &vtype));
4847   PetscCall(MatSetVecType(B, vtype));
4848 
4849   B->stencil.dim = mat->stencil.dim;
4850   B->stencil.noc = mat->stencil.noc;
4851   for (i = 0; i <= mat->stencil.dim; i++) {
4852     B->stencil.dims[i]   = mat->stencil.dims[i];
4853     B->stencil.starts[i] = mat->stencil.starts[i];
4854   }
4855 
4856   B->nooffproczerorows = mat->nooffproczerorows;
4857   B->nooffprocentries  = mat->nooffprocentries;
4858 
4859   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4860   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4861   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4862   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4863   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4864   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4865   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4866   PetscFunctionReturn(PETSC_SUCCESS);
4867 }
4868 
4869 /*@
4870    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4871 
4872    Logically Collective
4873 
4874    Input Parameter:
4875 .  mat - the matrix
4876 
4877    Output Parameter:
4878 .  v - the diagonal of the matrix
4879 
4880    Level: intermediate
4881 
4882    Note:
4883    Currently only correct in parallel for square matrices.
4884 
4885 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4886 @*/
4887 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4888 {
4889   PetscFunctionBegin;
4890   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4891   PetscValidType(mat, 1);
4892   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4893   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4894   MatCheckPreallocated(mat, 1);
4895 
4896   PetscUseTypeMethod(mat, getdiagonal, v);
4897   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4898   PetscFunctionReturn(PETSC_SUCCESS);
4899 }
4900 
4901 /*@C
4902    MatGetRowMin - Gets the minimum value (of the real part) of each
4903         row of the matrix
4904 
4905    Logically Collective
4906 
4907    Input Parameter:
4908 .  mat - the matrix
4909 
4910    Output Parameters:
4911 +  v - the vector for storing the maximums
4912 -  idx - the indices of the column found for each row (optional)
4913 
4914    Level: intermediate
4915 
4916    Note:
4917     The result of this call are the same as if one converted the matrix to dense format
4918       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4919 
4920     This code is only implemented for a couple of matrix formats.
4921 
4922 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4923           `MatGetRowMax()`
4924 @*/
4925 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4926 {
4927   PetscFunctionBegin;
4928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4929   PetscValidType(mat, 1);
4930   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4931   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4932 
4933   if (!mat->cmap->N) {
4934     PetscCall(VecSet(v, PETSC_MAX_REAL));
4935     if (idx) {
4936       PetscInt i, m = mat->rmap->n;
4937       for (i = 0; i < m; i++) idx[i] = -1;
4938     }
4939   } else {
4940     MatCheckPreallocated(mat, 1);
4941   }
4942   PetscUseTypeMethod(mat, getrowmin, v, idx);
4943   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4944   PetscFunctionReturn(PETSC_SUCCESS);
4945 }
4946 
4947 /*@C
4948    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4949         row of the matrix
4950 
4951    Logically Collective
4952 
4953    Input Parameter:
4954 .  mat - the matrix
4955 
4956    Output Parameters:
4957 +  v - the vector for storing the minimums
4958 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4959 
4960    Level: intermediate
4961 
4962    Notes:
4963     if a row is completely empty or has only 0.0 values then the idx[] value for that
4964     row is 0 (the first column).
4965 
4966     This code is only implemented for a couple of matrix formats.
4967 
4968 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4969 @*/
4970 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4971 {
4972   PetscFunctionBegin;
4973   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4974   PetscValidType(mat, 1);
4975   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4976   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4977   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4978 
4979   if (!mat->cmap->N) {
4980     PetscCall(VecSet(v, 0.0));
4981     if (idx) {
4982       PetscInt i, m = mat->rmap->n;
4983       for (i = 0; i < m; i++) idx[i] = -1;
4984     }
4985   } else {
4986     MatCheckPreallocated(mat, 1);
4987     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4988     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4989   }
4990   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4991   PetscFunctionReturn(PETSC_SUCCESS);
4992 }
4993 
4994 /*@C
4995    MatGetRowMax - Gets the maximum value (of the real part) of each
4996         row of the matrix
4997 
4998    Logically Collective
4999 
5000    Input Parameter:
5001 .  mat - the matrix
5002 
5003    Output Parameters:
5004 +  v - the vector for storing the maximums
5005 -  idx - the indices of the column found for each row (optional)
5006 
5007    Level: intermediate
5008 
5009    Notes:
5010     The result of this call are the same as if one converted the matrix to dense format
5011       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5012 
5013     This code is only implemented for a couple of matrix formats.
5014 
5015 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5016 @*/
5017 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5018 {
5019   PetscFunctionBegin;
5020   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5021   PetscValidType(mat, 1);
5022   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5023   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5024 
5025   if (!mat->cmap->N) {
5026     PetscCall(VecSet(v, PETSC_MIN_REAL));
5027     if (idx) {
5028       PetscInt i, m = mat->rmap->n;
5029       for (i = 0; i < m; i++) idx[i] = -1;
5030     }
5031   } else {
5032     MatCheckPreallocated(mat, 1);
5033     PetscUseTypeMethod(mat, getrowmax, v, idx);
5034   }
5035   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5036   PetscFunctionReturn(PETSC_SUCCESS);
5037 }
5038 
5039 /*@C
5040    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5041         row of the matrix
5042 
5043    Logically Collective
5044 
5045    Input Parameter:
5046 .  mat - the matrix
5047 
5048    Output Parameters:
5049 +  v - the vector for storing the maximums
5050 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5051 
5052    Level: intermediate
5053 
5054    Notes:
5055     if a row is completely empty or has only 0.0 values then the idx[] value for that
5056     row is 0 (the first column).
5057 
5058     This code is only implemented for a couple of matrix formats.
5059 
5060 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5061 @*/
5062 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5063 {
5064   PetscFunctionBegin;
5065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5066   PetscValidType(mat, 1);
5067   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5068   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5069 
5070   if (!mat->cmap->N) {
5071     PetscCall(VecSet(v, 0.0));
5072     if (idx) {
5073       PetscInt i, m = mat->rmap->n;
5074       for (i = 0; i < m; i++) idx[i] = -1;
5075     }
5076   } else {
5077     MatCheckPreallocated(mat, 1);
5078     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5079     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5080   }
5081   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5082   PetscFunctionReturn(PETSC_SUCCESS);
5083 }
5084 
5085 /*@
5086    MatGetRowSum - Gets the sum of each row of the matrix
5087 
5088    Logically or Neighborhood Collective
5089 
5090    Input Parameter:
5091 .  mat - the matrix
5092 
5093    Output Parameter:
5094 .  v - the vector for storing the sum of rows
5095 
5096    Level: intermediate
5097 
5098    Notes:
5099     This code is slow since it is not currently specialized for different formats
5100 
5101 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5102 @*/
5103 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5104 {
5105   Vec ones;
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   MatCheckPreallocated(mat, 1);
5113   PetscCall(MatCreateVecs(mat, &ones, NULL));
5114   PetscCall(VecSet(ones, 1.));
5115   PetscCall(MatMult(mat, ones, v));
5116   PetscCall(VecDestroy(&ones));
5117   PetscFunctionReturn(PETSC_SUCCESS);
5118 }
5119 
5120 /*@
5121    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5122    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5123 
5124    Collective
5125 
5126    Input Parameter:
5127 .  mat - the matrix to provide the transpose
5128 
5129    Output Parameter:
5130 .  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
5131 
5132    Level: advanced
5133 
5134    Note:
5135    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
5136    routine allows bypassing that call.
5137 
5138 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5139 @*/
5140 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5141 {
5142   PetscContainer  rB = NULL;
5143   MatParentState *rb = NULL;
5144 
5145   PetscFunctionBegin;
5146   PetscCall(PetscNew(&rb));
5147   rb->id    = ((PetscObject)mat)->id;
5148   rb->state = 0;
5149   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5150   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5151   PetscCall(PetscContainerSetPointer(rB, rb));
5152   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5153   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5154   PetscCall(PetscObjectDereference((PetscObject)rB));
5155   PetscFunctionReturn(PETSC_SUCCESS);
5156 }
5157 
5158 /*@
5159    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5160 
5161    Collective
5162 
5163    Input Parameters:
5164 +  mat - the matrix to transpose
5165 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5166 
5167    Output Parameter:
5168 .  B - the transpose
5169 
5170    Level: intermediate
5171 
5172    Notes:
5173      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5174 
5175      `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
5176      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5177 
5178      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.
5179 
5180      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5181 
5182      If mat is unchanged from the last call this function returns immediately without recomputing the result
5183 
5184      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5185 
5186 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5187           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5188 @*/
5189 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5190 {
5191   PetscContainer  rB = NULL;
5192   MatParentState *rb = NULL;
5193 
5194   PetscFunctionBegin;
5195   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5196   PetscValidType(mat, 1);
5197   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5198   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5199   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5200   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5201   MatCheckPreallocated(mat, 1);
5202   if (reuse == MAT_REUSE_MATRIX) {
5203     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5204     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5205     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5206     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5207     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5208   }
5209 
5210   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5211   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5212     PetscUseTypeMethod(mat, transpose, reuse, B);
5213     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5214   }
5215   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5216 
5217   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5218   if (reuse != MAT_INPLACE_MATRIX) {
5219     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5220     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5221     rb->state        = ((PetscObject)mat)->state;
5222     rb->nonzerostate = mat->nonzerostate;
5223   }
5224   PetscFunctionReturn(PETSC_SUCCESS);
5225 }
5226 
5227 /*@
5228    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5229 
5230    Collective
5231 
5232    Input Parameter:
5233 .  A - the matrix to transpose
5234 
5235    Output Parameter:
5236 .  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
5237       numerical portion.
5238 
5239    Level: intermediate
5240 
5241    Note:
5242    This is not supported for many matrix types, use `MatTranspose()` in those cases
5243 
5244 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5245 @*/
5246 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5247 {
5248   PetscFunctionBegin;
5249   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5250   PetscValidType(A, 1);
5251   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5252   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5253   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5254   PetscUseTypeMethod(A, transposesymbolic, B);
5255   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5256 
5257   PetscCall(MatTransposeSetPrecursor(A, *B));
5258   PetscFunctionReturn(PETSC_SUCCESS);
5259 }
5260 
5261 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5262 {
5263   PetscContainer  rB;
5264   MatParentState *rb;
5265 
5266   PetscFunctionBegin;
5267   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5268   PetscValidType(A, 1);
5269   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5270   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5271   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5272   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5273   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5274   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5275   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5276   PetscFunctionReturn(PETSC_SUCCESS);
5277 }
5278 
5279 /*@
5280    MatIsTranspose - Test whether a matrix is another one's transpose,
5281         or its own, in which case it tests symmetry.
5282 
5283    Collective
5284 
5285    Input Parameters:
5286 +  A - the matrix to test
5287 .  B - the matrix to test against, this can equal the first parameter
5288 -  tol - tolerance, differences between entries smaller than this are counted as zero
5289 
5290    Output Parameter:
5291 .  flg - the result
5292 
5293    Level: intermediate
5294 
5295    Notes:
5296    Only available for `MATAIJ` matrices.
5297 
5298    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5299    test involves parallel copies of the block-offdiagonal parts of the matrix.
5300 
5301 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5302 @*/
5303 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5304 {
5305   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5306 
5307   PetscFunctionBegin;
5308   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5309   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5310   PetscValidBoolPointer(flg, 4);
5311   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5312   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5313   *flg = PETSC_FALSE;
5314   if (f && g) {
5315     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5316     PetscCall((*f)(A, B, tol, flg));
5317   } else {
5318     MatType mattype;
5319 
5320     PetscCall(MatGetType(f ? B : A, &mattype));
5321     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5322   }
5323   PetscFunctionReturn(PETSC_SUCCESS);
5324 }
5325 
5326 /*@
5327    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5328 
5329    Collective
5330 
5331    Input Parameters:
5332 +  mat - the matrix to transpose and complex conjugate
5333 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5334 
5335    Output Parameter:
5336 .  B - the Hermitian transpose
5337 
5338    Level: intermediate
5339 
5340 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5341 @*/
5342 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5343 {
5344   PetscFunctionBegin;
5345   PetscCall(MatTranspose(mat, reuse, B));
5346 #if defined(PETSC_USE_COMPLEX)
5347   PetscCall(MatConjugate(*B));
5348 #endif
5349   PetscFunctionReturn(PETSC_SUCCESS);
5350 }
5351 
5352 /*@
5353    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5354 
5355    Collective
5356 
5357    Input Parameters:
5358 +  A - the matrix to test
5359 .  B - the matrix to test against, this can equal the first parameter
5360 -  tol - tolerance, differences between entries smaller than this are counted as zero
5361 
5362    Output Parameter:
5363 .  flg - the result
5364 
5365    Level: intermediate
5366 
5367    Notes:
5368    Only available for `MATAIJ` matrices.
5369 
5370    The sequential algorithm
5371    has a running time of the order of the number of nonzeros; the parallel
5372    test involves parallel copies of the block-offdiagonal parts of the matrix.
5373 
5374 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5375 @*/
5376 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5377 {
5378   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5379 
5380   PetscFunctionBegin;
5381   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5382   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5383   PetscValidBoolPointer(flg, 4);
5384   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5385   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5386   if (f && g) {
5387     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5388     PetscCall((*f)(A, B, tol, flg));
5389   }
5390   PetscFunctionReturn(PETSC_SUCCESS);
5391 }
5392 
5393 /*@
5394    MatPermute - Creates a new matrix with rows and columns permuted from the
5395    original.
5396 
5397    Collective
5398 
5399    Input Parameters:
5400 +  mat - the matrix to permute
5401 .  row - row permutation, each processor supplies only the permutation for its rows
5402 -  col - column permutation, each processor supplies only the permutation for its columns
5403 
5404    Output Parameter:
5405 .  B - the permuted matrix
5406 
5407    Level: advanced
5408 
5409    Note:
5410    The index sets map from row/col of permuted matrix to row/col of original matrix.
5411    The index sets should be on the same communicator as mat and have the same local sizes.
5412 
5413    Developer Note:
5414      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5415      exploit the fact that row and col are permutations, consider implementing the
5416      more general `MatCreateSubMatrix()` instead.
5417 
5418 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5419 @*/
5420 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5421 {
5422   PetscFunctionBegin;
5423   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5424   PetscValidType(mat, 1);
5425   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5426   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5427   PetscValidPointer(B, 4);
5428   PetscCheckSameComm(mat, 1, row, 2);
5429   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5430   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5431   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5432   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5433   MatCheckPreallocated(mat, 1);
5434 
5435   if (mat->ops->permute) {
5436     PetscUseTypeMethod(mat, permute, row, col, B);
5437     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5438   } else {
5439     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5440   }
5441   PetscFunctionReturn(PETSC_SUCCESS);
5442 }
5443 
5444 /*@
5445    MatEqual - Compares two matrices.
5446 
5447    Collective
5448 
5449    Input Parameters:
5450 +  A - the first matrix
5451 -  B - the second matrix
5452 
5453    Output Parameter:
5454 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5455 
5456    Level: intermediate
5457 
5458 .seealso: [](chapter_matrices), `Mat`
5459 @*/
5460 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5461 {
5462   PetscFunctionBegin;
5463   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5464   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5465   PetscValidType(A, 1);
5466   PetscValidType(B, 2);
5467   PetscValidBoolPointer(flg, 3);
5468   PetscCheckSameComm(A, 1, B, 2);
5469   MatCheckPreallocated(A, 1);
5470   MatCheckPreallocated(B, 2);
5471   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5472   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5473   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5474              B->cmap->N);
5475   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5476     PetscUseTypeMethod(A, equal, B, flg);
5477   } else {
5478     PetscCall(MatMultEqual(A, B, 10, flg));
5479   }
5480   PetscFunctionReturn(PETSC_SUCCESS);
5481 }
5482 
5483 /*@
5484    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5485    matrices that are stored as vectors.  Either of the two scaling
5486    matrices can be `NULL`.
5487 
5488    Collective
5489 
5490    Input Parameters:
5491 +  mat - the matrix to be scaled
5492 .  l - the left scaling vector (or `NULL`)
5493 -  r - the right scaling vector (or `NULL`)
5494 
5495    Level: intermediate
5496 
5497    Note:
5498    `MatDiagonalScale()` computes A = LAR, where
5499    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5500    The L scales the rows of the matrix, the R scales the columns of the matrix.
5501 
5502 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5503 @*/
5504 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5505 {
5506   PetscFunctionBegin;
5507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5508   PetscValidType(mat, 1);
5509   if (l) {
5510     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5511     PetscCheckSameComm(mat, 1, l, 2);
5512   }
5513   if (r) {
5514     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5515     PetscCheckSameComm(mat, 1, r, 3);
5516   }
5517   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5518   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5519   MatCheckPreallocated(mat, 1);
5520   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5521 
5522   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5523   PetscUseTypeMethod(mat, diagonalscale, l, r);
5524   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5525   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5526   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5527   PetscFunctionReturn(PETSC_SUCCESS);
5528 }
5529 
5530 /*@
5531     MatScale - Scales all elements of a matrix by a given number.
5532 
5533     Logically Collective
5534 
5535     Input Parameters:
5536 +   mat - the matrix to be scaled
5537 -   a  - the scaling value
5538 
5539     Level: intermediate
5540 
5541 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5542 @*/
5543 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5544 {
5545   PetscFunctionBegin;
5546   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5547   PetscValidType(mat, 1);
5548   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5549   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5550   PetscValidLogicalCollectiveScalar(mat, a, 2);
5551   MatCheckPreallocated(mat, 1);
5552 
5553   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5554   if (a != (PetscScalar)1.0) {
5555     PetscUseTypeMethod(mat, scale, a);
5556     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5557   }
5558   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5559   PetscFunctionReturn(PETSC_SUCCESS);
5560 }
5561 
5562 /*@
5563    MatNorm - Calculates various norms of a matrix.
5564 
5565    Collective
5566 
5567    Input Parameters:
5568 +  mat - the matrix
5569 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5570 
5571    Output Parameter:
5572 .  nrm - the resulting norm
5573 
5574    Level: intermediate
5575 
5576 .seealso: [](chapter_matrices), `Mat`
5577 @*/
5578 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5579 {
5580   PetscFunctionBegin;
5581   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5582   PetscValidType(mat, 1);
5583   PetscValidRealPointer(nrm, 3);
5584 
5585   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5586   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5587   MatCheckPreallocated(mat, 1);
5588 
5589   PetscUseTypeMethod(mat, norm, type, nrm);
5590   PetscFunctionReturn(PETSC_SUCCESS);
5591 }
5592 
5593 /*
5594      This variable is used to prevent counting of MatAssemblyBegin() that
5595    are called from within a MatAssemblyEnd().
5596 */
5597 static PetscInt MatAssemblyEnd_InUse = 0;
5598 /*@
5599    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5600    be called after completing all calls to `MatSetValues()`.
5601 
5602    Collective
5603 
5604    Input Parameters:
5605 +  mat - the matrix
5606 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5607 
5608    Level: beginner
5609 
5610    Notes:
5611    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5612    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5613 
5614    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5615    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5616    using the matrix.
5617 
5618    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5619    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
5620    a global collective operation requiring all processes that share the matrix.
5621 
5622    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5623    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5624    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5625 
5626 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5627 @*/
5628 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5629 {
5630   PetscFunctionBegin;
5631   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5632   PetscValidType(mat, 1);
5633   MatCheckPreallocated(mat, 1);
5634   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5635   if (mat->assembled) {
5636     mat->was_assembled = PETSC_TRUE;
5637     mat->assembled     = PETSC_FALSE;
5638   }
5639 
5640   if (!MatAssemblyEnd_InUse) {
5641     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5642     PetscTryTypeMethod(mat, assemblybegin, type);
5643     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5644   } else PetscTryTypeMethod(mat, assemblybegin, type);
5645   PetscFunctionReturn(PETSC_SUCCESS);
5646 }
5647 
5648 /*@
5649    MatAssembled - Indicates if a matrix has been assembled and is ready for
5650      use; for example, in matrix-vector product.
5651 
5652    Not Collective
5653 
5654    Input Parameter:
5655 .  mat - the matrix
5656 
5657    Output Parameter:
5658 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5659 
5660    Level: advanced
5661 
5662 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5663 @*/
5664 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5665 {
5666   PetscFunctionBegin;
5667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5668   PetscValidBoolPointer(assembled, 2);
5669   *assembled = mat->assembled;
5670   PetscFunctionReturn(PETSC_SUCCESS);
5671 }
5672 
5673 /*@
5674    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5675    be called after `MatAssemblyBegin()`.
5676 
5677    Collective
5678 
5679    Input Parameters:
5680 +  mat - the matrix
5681 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5682 
5683    Options Database Keys:
5684 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5685 .  -mat_view ::ascii_info_detail - Prints more detailed info
5686 .  -mat_view - Prints matrix in ASCII format
5687 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5688 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5689 .  -display <name> - Sets display name (default is host)
5690 .  -draw_pause <sec> - Sets number of seconds to pause after display
5691 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5692 .  -viewer_socket_machine <machine> - Machine to use for socket
5693 .  -viewer_socket_port <port> - Port number to use for socket
5694 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5695 
5696    Level: beginner
5697 
5698 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5699 @*/
5700 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5701 {
5702   static PetscInt inassm = 0;
5703   PetscBool       flg    = PETSC_FALSE;
5704 
5705   PetscFunctionBegin;
5706   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5707   PetscValidType(mat, 1);
5708 
5709   inassm++;
5710   MatAssemblyEnd_InUse++;
5711   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5712     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5713     PetscTryTypeMethod(mat, assemblyend, type);
5714     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5715   } else PetscTryTypeMethod(mat, assemblyend, type);
5716 
5717   /* Flush assembly is not a true assembly */
5718   if (type != MAT_FLUSH_ASSEMBLY) {
5719     if (mat->num_ass) {
5720       if (!mat->symmetry_eternal) {
5721         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5722         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5723       }
5724       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5725       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5726     }
5727     mat->num_ass++;
5728     mat->assembled        = PETSC_TRUE;
5729     mat->ass_nonzerostate = mat->nonzerostate;
5730   }
5731 
5732   mat->insertmode = NOT_SET_VALUES;
5733   MatAssemblyEnd_InUse--;
5734   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5735   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5736     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5737 
5738     if (mat->checksymmetryonassembly) {
5739       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5740       if (flg) {
5741         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5742       } else {
5743         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5744       }
5745     }
5746     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5747   }
5748   inassm--;
5749   PetscFunctionReturn(PETSC_SUCCESS);
5750 }
5751 
5752 /*@
5753    MatSetOption - Sets a parameter option for a matrix. Some options
5754    may be specific to certain storage formats.  Some options
5755    determine how values will be inserted (or added). Sorted,
5756    row-oriented input will generally assemble the fastest. The default
5757    is row-oriented.
5758 
5759    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5760 
5761    Input Parameters:
5762 +  mat - the matrix
5763 .  option - the option, one of those listed below (and possibly others),
5764 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5765 
5766   Options Describing Matrix Structure:
5767 +    `MAT_SPD` - symmetric positive definite
5768 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5769 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5770 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5771 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5772 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5773 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5774 
5775    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5776    do not need to be computed (usually at a high cost)
5777 
5778    Options For Use with `MatSetValues()`:
5779    Insert a logically dense subblock, which can be
5780 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5781 
5782    These options reflect the data you pass in with `MatSetValues()`; it has
5783    nothing to do with how the data is stored internally in the matrix
5784    data structure.
5785 
5786    When (re)assembling a matrix, we can restrict the input for
5787    efficiency/debugging purposes.  These options include
5788 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5789 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5790 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5791 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5792 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5793 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5794         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5795         performance for very large process counts.
5796 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5797         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5798         functions, instead sending only neighbor messages.
5799 
5800    Level: intermediate
5801 
5802    Notes:
5803    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5804 
5805    Some options are relevant only for particular matrix types and
5806    are thus ignored by others.  Other options are not supported by
5807    certain matrix types and will generate an error message if set.
5808 
5809    If using Fortran to compute a matrix, one may need to
5810    use the column-oriented option (or convert to the row-oriented
5811    format).
5812 
5813    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5814    that would generate a new entry in the nonzero structure is instead
5815    ignored.  Thus, if memory has not already been allocated for this particular
5816    data, then the insertion is ignored. For dense matrices, in which
5817    the entire array is allocated, no entries are ever ignored.
5818    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5819 
5820    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5821    that would generate a new entry in the nonzero structure instead produces
5822    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
5823 
5824    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5825    that would generate a new entry that has not been preallocated will
5826    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5827    only.) This is a useful flag when debugging matrix memory preallocation.
5828    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5829 
5830    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5831    other processors should be dropped, rather than stashed.
5832    This is useful if you know that the "owning" processor is also
5833    always generating the correct matrix entries, so that PETSc need
5834    not transfer duplicate entries generated on another processor.
5835 
5836    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5837    searches during matrix assembly. When this flag is set, the hash table
5838    is created during the first matrix assembly. This hash table is
5839    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5840    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5841    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5842    supported by `MATMPIBAIJ` format only.
5843 
5844    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5845    are kept in the nonzero structure
5846 
5847    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5848    a zero location in the matrix
5849 
5850    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5851 
5852    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5853         zero row routines and thus improves performance for very large process counts.
5854 
5855    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5856         part of the matrix (since they should match the upper triangular part).
5857 
5858    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5859                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5860                      with finite difference schemes with non-periodic boundary conditions.
5861 
5862    Developer Note:
5863    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5864    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5865    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5866    not changed.
5867 
5868 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5869 @*/
5870 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5871 {
5872   PetscFunctionBegin;
5873   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5874   if (op > 0) {
5875     PetscValidLogicalCollectiveEnum(mat, op, 2);
5876     PetscValidLogicalCollectiveBool(mat, flg, 3);
5877   }
5878 
5879   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);
5880 
5881   switch (op) {
5882   case MAT_FORCE_DIAGONAL_ENTRIES:
5883     mat->force_diagonals = flg;
5884     PetscFunctionReturn(PETSC_SUCCESS);
5885   case MAT_NO_OFF_PROC_ENTRIES:
5886     mat->nooffprocentries = flg;
5887     PetscFunctionReturn(PETSC_SUCCESS);
5888   case MAT_SUBSET_OFF_PROC_ENTRIES:
5889     mat->assembly_subset = flg;
5890     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5891 #if !defined(PETSC_HAVE_MPIUNI)
5892       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5893 #endif
5894       mat->stash.first_assembly_done = PETSC_FALSE;
5895     }
5896     PetscFunctionReturn(PETSC_SUCCESS);
5897   case MAT_NO_OFF_PROC_ZERO_ROWS:
5898     mat->nooffproczerorows = flg;
5899     PetscFunctionReturn(PETSC_SUCCESS);
5900   case MAT_SPD:
5901     if (flg) {
5902       mat->spd                    = PETSC_BOOL3_TRUE;
5903       mat->symmetric              = PETSC_BOOL3_TRUE;
5904       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5905     } else {
5906       mat->spd = PETSC_BOOL3_FALSE;
5907     }
5908     break;
5909   case MAT_SYMMETRIC:
5910     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5911     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5912 #if !defined(PETSC_USE_COMPLEX)
5913     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5914 #endif
5915     break;
5916   case MAT_HERMITIAN:
5917     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5918     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5919 #if !defined(PETSC_USE_COMPLEX)
5920     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5921 #endif
5922     break;
5923   case MAT_STRUCTURALLY_SYMMETRIC:
5924     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5925     break;
5926   case MAT_SYMMETRY_ETERNAL:
5927     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");
5928     mat->symmetry_eternal = flg;
5929     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5930     break;
5931   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5932     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");
5933     mat->structural_symmetry_eternal = flg;
5934     break;
5935   case MAT_SPD_ETERNAL:
5936     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");
5937     mat->spd_eternal = flg;
5938     if (flg) {
5939       mat->structural_symmetry_eternal = PETSC_TRUE;
5940       mat->symmetry_eternal            = PETSC_TRUE;
5941     }
5942     break;
5943   case MAT_STRUCTURE_ONLY:
5944     mat->structure_only = flg;
5945     break;
5946   case MAT_SORTED_FULL:
5947     mat->sortedfull = flg;
5948     break;
5949   default:
5950     break;
5951   }
5952   PetscTryTypeMethod(mat, setoption, op, flg);
5953   PetscFunctionReturn(PETSC_SUCCESS);
5954 }
5955 
5956 /*@
5957    MatGetOption - Gets a parameter option that has been set for a matrix.
5958 
5959    Logically Collective
5960 
5961    Input Parameters:
5962 +  mat - the matrix
5963 -  option - the option, this only responds to certain options, check the code for which ones
5964 
5965    Output Parameter:
5966 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5967 
5968    Level: intermediate
5969 
5970     Notes:
5971     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5972 
5973     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5974     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5975 
5976 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5977     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5978 @*/
5979 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5980 {
5981   PetscFunctionBegin;
5982   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5983   PetscValidType(mat, 1);
5984 
5985   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);
5986   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()");
5987 
5988   switch (op) {
5989   case MAT_NO_OFF_PROC_ENTRIES:
5990     *flg = mat->nooffprocentries;
5991     break;
5992   case MAT_NO_OFF_PROC_ZERO_ROWS:
5993     *flg = mat->nooffproczerorows;
5994     break;
5995   case MAT_SYMMETRIC:
5996     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5997     break;
5998   case MAT_HERMITIAN:
5999     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6000     break;
6001   case MAT_STRUCTURALLY_SYMMETRIC:
6002     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6003     break;
6004   case MAT_SPD:
6005     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6006     break;
6007   case MAT_SYMMETRY_ETERNAL:
6008     *flg = mat->symmetry_eternal;
6009     break;
6010   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6011     *flg = mat->symmetry_eternal;
6012     break;
6013   default:
6014     break;
6015   }
6016   PetscFunctionReturn(PETSC_SUCCESS);
6017 }
6018 
6019 /*@
6020    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6021    this routine retains the old nonzero structure.
6022 
6023    Logically Collective
6024 
6025    Input Parameter:
6026 .  mat - the matrix
6027 
6028    Level: intermediate
6029 
6030    Note:
6031     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.
6032    See the Performance chapter of the users manual for information on preallocating matrices.
6033 
6034 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6035 @*/
6036 PetscErrorCode MatZeroEntries(Mat mat)
6037 {
6038   PetscFunctionBegin;
6039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6040   PetscValidType(mat, 1);
6041   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6042   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");
6043   MatCheckPreallocated(mat, 1);
6044 
6045   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6046   PetscUseTypeMethod(mat, zeroentries);
6047   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6048   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6049   PetscFunctionReturn(PETSC_SUCCESS);
6050 }
6051 
6052 /*@
6053    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6054    of a set of rows and columns of a matrix.
6055 
6056    Collective
6057 
6058    Input Parameters:
6059 +  mat - the matrix
6060 .  numRows - the number of rows/columns to zero
6061 .  rows - the global row indices
6062 .  diag - value put in the diagonal of the eliminated rows
6063 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6064 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6065 
6066    Level: intermediate
6067 
6068    Notes:
6069    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6070 
6071    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6072    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
6073 
6074    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6075    Krylov method to take advantage of the known solution on the zeroed rows.
6076 
6077    For the parallel case, all processes that share the matrix (i.e.,
6078    those in the communicator used for matrix creation) MUST call this
6079    routine, regardless of whether any rows being zeroed are owned by
6080    them.
6081 
6082    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6083 
6084    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6085    list only rows local to itself).
6086 
6087    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6088 
6089 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6090           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6091 @*/
6092 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6093 {
6094   PetscFunctionBegin;
6095   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6096   PetscValidType(mat, 1);
6097   if (numRows) PetscValidIntPointer(rows, 3);
6098   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6099   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6100   MatCheckPreallocated(mat, 1);
6101 
6102   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6103   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6105   PetscFunctionReturn(PETSC_SUCCESS);
6106 }
6107 
6108 /*@
6109    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6110    of a set of rows and columns of a matrix.
6111 
6112    Collective
6113 
6114    Input Parameters:
6115 +  mat - the matrix
6116 .  is - the rows to zero
6117 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6118 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6119 -  b - optional vector of right hand side, that will be adjusted by provided solution
6120 
6121    Level: intermediate
6122 
6123    Note:
6124    See `MatZeroRowsColumns()` for details on how this routine operates.
6125 
6126 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6127           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6128 @*/
6129 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6130 {
6131   PetscInt        numRows;
6132   const PetscInt *rows;
6133 
6134   PetscFunctionBegin;
6135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6136   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6137   PetscValidType(mat, 1);
6138   PetscValidType(is, 2);
6139   PetscCall(ISGetLocalSize(is, &numRows));
6140   PetscCall(ISGetIndices(is, &rows));
6141   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6142   PetscCall(ISRestoreIndices(is, &rows));
6143   PetscFunctionReturn(PETSC_SUCCESS);
6144 }
6145 
6146 /*@
6147    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6148    of a set of rows of a matrix.
6149 
6150    Collective
6151 
6152    Input Parameters:
6153 +  mat - the matrix
6154 .  numRows - the number of rows to zero
6155 .  rows - the global row indices
6156 .  diag - value put in the diagonal of the zeroed rows
6157 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6158 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6159 
6160    Level: intermediate
6161 
6162    Notes:
6163    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6164 
6165    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6166 
6167    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6168    Krylov method to take advantage of the known solution on the zeroed rows.
6169 
6170    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)
6171    from the matrix.
6172 
6173    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6174    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
6175    formats this does not alter the nonzero structure.
6176 
6177    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6178    of the matrix is not changed the values are
6179    merely zeroed.
6180 
6181    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6182    formats can optionally remove the main diagonal entry from the
6183    nonzero structure as well, by passing 0.0 as the final argument).
6184 
6185    For the parallel case, all processes that share the matrix (i.e.,
6186    those in the communicator used for matrix creation) MUST call this
6187    routine, regardless of whether any rows being zeroed are owned by
6188    them.
6189 
6190    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6191    list only rows local to itself).
6192 
6193    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6194    owns that are to be zeroed. This saves a global synchronization in the implementation.
6195 
6196 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6197           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6198 @*/
6199 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6200 {
6201   PetscFunctionBegin;
6202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6203   PetscValidType(mat, 1);
6204   if (numRows) PetscValidIntPointer(rows, 3);
6205   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6206   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6207   MatCheckPreallocated(mat, 1);
6208 
6209   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6210   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6211   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6212   PetscFunctionReturn(PETSC_SUCCESS);
6213 }
6214 
6215 /*@
6216    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6217    of a set of rows of a matrix.
6218 
6219    Collective
6220 
6221    Input Parameters:
6222 +  mat - the matrix
6223 .  is - index set of rows to remove (if `NULL` then no row is removed)
6224 .  diag - value put in all diagonals of eliminated rows
6225 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6226 -  b - optional vector of right hand side, that will be adjusted by provided solution
6227 
6228    Level: intermediate
6229 
6230    Note:
6231    See `MatZeroRows()` for details on how this routine operates.
6232 
6233 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6234           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6235 @*/
6236 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6237 {
6238   PetscInt        numRows = 0;
6239   const PetscInt *rows    = NULL;
6240 
6241   PetscFunctionBegin;
6242   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6243   PetscValidType(mat, 1);
6244   if (is) {
6245     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6246     PetscCall(ISGetLocalSize(is, &numRows));
6247     PetscCall(ISGetIndices(is, &rows));
6248   }
6249   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6250   if (is) PetscCall(ISRestoreIndices(is, &rows));
6251   PetscFunctionReturn(PETSC_SUCCESS);
6252 }
6253 
6254 /*@
6255    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6256    of a set of rows of a matrix. These rows must be local to the process.
6257 
6258    Collective
6259 
6260    Input Parameters:
6261 +  mat - the matrix
6262 .  numRows - the number of rows to remove
6263 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6264 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6265 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6266 -  b - optional vector of right hand side, that will be adjusted by provided solution
6267 
6268    Level: intermediate
6269 
6270    Notes:
6271    See `MatZeroRows()` for details on how this routine operates.
6272 
6273    The grid coordinates are across the entire grid, not just the local portion
6274 
6275    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6276    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6277    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6278    `DM_BOUNDARY_PERIODIC` boundary type.
6279 
6280    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
6281    a single value per point) you can skip filling those indices.
6282 
6283    Fortran Note:
6284    `idxm` and `idxn` should be declared as
6285 $     MatStencil idxm(4, m)
6286    and the values inserted using
6287 .vb
6288     idxm(MatStencil_i, 1) = i
6289     idxm(MatStencil_j, 1) = j
6290     idxm(MatStencil_k, 1) = k
6291     idxm(MatStencil_c, 1) = c
6292    etc
6293 .ve
6294 
6295 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6296           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6297 @*/
6298 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6299 {
6300   PetscInt  dim    = mat->stencil.dim;
6301   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6302   PetscInt *dims   = mat->stencil.dims + 1;
6303   PetscInt *starts = mat->stencil.starts;
6304   PetscInt *dxm    = (PetscInt *)rows;
6305   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6306 
6307   PetscFunctionBegin;
6308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6309   PetscValidType(mat, 1);
6310   if (numRows) PetscValidPointer(rows, 3);
6311 
6312   PetscCall(PetscMalloc1(numRows, &jdxm));
6313   for (i = 0; i < numRows; ++i) {
6314     /* Skip unused dimensions (they are ordered k, j, i, c) */
6315     for (j = 0; j < 3 - sdim; ++j) dxm++;
6316     /* Local index in X dir */
6317     tmp = *dxm++ - starts[0];
6318     /* Loop over remaining dimensions */
6319     for (j = 0; j < dim - 1; ++j) {
6320       /* If nonlocal, set index to be negative */
6321       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6322       /* Update local index */
6323       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6324     }
6325     /* Skip component slot if necessary */
6326     if (mat->stencil.noc) dxm++;
6327     /* Local row number */
6328     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6329   }
6330   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6331   PetscCall(PetscFree(jdxm));
6332   PetscFunctionReturn(PETSC_SUCCESS);
6333 }
6334 
6335 /*@
6336    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6337    of a set of rows and columns of a matrix.
6338 
6339    Collective
6340 
6341    Input Parameters:
6342 +  mat - the matrix
6343 .  numRows - the number of rows/columns to remove
6344 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6345 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6346 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6347 -  b - optional vector of right hand side, that will be adjusted by provided solution
6348 
6349    Level: intermediate
6350 
6351    Notes:
6352    See `MatZeroRowsColumns()` for details on how this routine operates.
6353 
6354    The grid coordinates are across the entire grid, not just the local portion
6355 
6356    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6357    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6358    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6359    `DM_BOUNDARY_PERIODIC` boundary type.
6360 
6361    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
6362    a single value per point) you can skip filling those indices.
6363 
6364    Fortran Note:
6365    `idxm` and `idxn` should be declared as
6366 $     MatStencil idxm(4, m)
6367    and the values inserted using
6368 .vb
6369     idxm(MatStencil_i, 1) = i
6370     idxm(MatStencil_j, 1) = j
6371     idxm(MatStencil_k, 1) = k
6372     idxm(MatStencil_c, 1) = c
6373     etc
6374 .ve
6375 
6376 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6377           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6378 @*/
6379 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6380 {
6381   PetscInt  dim    = mat->stencil.dim;
6382   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6383   PetscInt *dims   = mat->stencil.dims + 1;
6384   PetscInt *starts = mat->stencil.starts;
6385   PetscInt *dxm    = (PetscInt *)rows;
6386   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6387 
6388   PetscFunctionBegin;
6389   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6390   PetscValidType(mat, 1);
6391   if (numRows) PetscValidPointer(rows, 3);
6392 
6393   PetscCall(PetscMalloc1(numRows, &jdxm));
6394   for (i = 0; i < numRows; ++i) {
6395     /* Skip unused dimensions (they are ordered k, j, i, c) */
6396     for (j = 0; j < 3 - sdim; ++j) dxm++;
6397     /* Local index in X dir */
6398     tmp = *dxm++ - starts[0];
6399     /* Loop over remaining dimensions */
6400     for (j = 0; j < dim - 1; ++j) {
6401       /* If nonlocal, set index to be negative */
6402       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6403       /* Update local index */
6404       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6405     }
6406     /* Skip component slot if necessary */
6407     if (mat->stencil.noc) dxm++;
6408     /* Local row number */
6409     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6410   }
6411   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6412   PetscCall(PetscFree(jdxm));
6413   PetscFunctionReturn(PETSC_SUCCESS);
6414 }
6415 
6416 /*@C
6417    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6418    of a set of rows of a matrix; using local numbering of rows.
6419 
6420    Collective
6421 
6422    Input Parameters:
6423 +  mat - the matrix
6424 .  numRows - the number of rows to remove
6425 .  rows - the local row indices
6426 .  diag - value put in all diagonals of eliminated rows
6427 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6428 -  b - optional vector of right hand side, that will be adjusted by provided solution
6429 
6430    Level: intermediate
6431 
6432    Notes:
6433    Before calling `MatZeroRowsLocal()`, the user must first set the
6434    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6435 
6436    See `MatZeroRows()` for details on how this routine operates.
6437 
6438 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6439           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6440 @*/
6441 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6442 {
6443   PetscFunctionBegin;
6444   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6445   PetscValidType(mat, 1);
6446   if (numRows) PetscValidIntPointer(rows, 3);
6447   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6448   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6449   MatCheckPreallocated(mat, 1);
6450 
6451   if (mat->ops->zerorowslocal) {
6452     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6453   } else {
6454     IS              is, newis;
6455     const PetscInt *newRows;
6456 
6457     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6458     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6459     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6460     PetscCall(ISGetIndices(newis, &newRows));
6461     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6462     PetscCall(ISRestoreIndices(newis, &newRows));
6463     PetscCall(ISDestroy(&newis));
6464     PetscCall(ISDestroy(&is));
6465   }
6466   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6467   PetscFunctionReturn(PETSC_SUCCESS);
6468 }
6469 
6470 /*@
6471    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6472    of a set of rows of a matrix; using local numbering of rows.
6473 
6474    Collective
6475 
6476    Input Parameters:
6477 +  mat - the matrix
6478 .  is - index set of rows to remove
6479 .  diag - value put in all diagonals of eliminated rows
6480 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6481 -  b - optional vector of right hand side, that will be adjusted by provided solution
6482 
6483    Level: intermediate
6484 
6485    Notes:
6486    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6487    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6488 
6489    See `MatZeroRows()` for details on how this routine operates.
6490 
6491 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6492           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6493 @*/
6494 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6495 {
6496   PetscInt        numRows;
6497   const PetscInt *rows;
6498 
6499   PetscFunctionBegin;
6500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6501   PetscValidType(mat, 1);
6502   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6503   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6504   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6505   MatCheckPreallocated(mat, 1);
6506 
6507   PetscCall(ISGetLocalSize(is, &numRows));
6508   PetscCall(ISGetIndices(is, &rows));
6509   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6510   PetscCall(ISRestoreIndices(is, &rows));
6511   PetscFunctionReturn(PETSC_SUCCESS);
6512 }
6513 
6514 /*@
6515    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6516    of a set of rows and columns of a matrix; using local numbering of rows.
6517 
6518    Collective
6519 
6520    Input Parameters:
6521 +  mat - the matrix
6522 .  numRows - the number of rows to remove
6523 .  rows - the global row indices
6524 .  diag - value put in all diagonals of eliminated rows
6525 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6526 -  b - optional vector of right hand side, that will be adjusted by provided solution
6527 
6528    Level: intermediate
6529 
6530    Notes:
6531    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6532    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6533 
6534    See `MatZeroRowsColumns()` for details on how this routine operates.
6535 
6536 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6537           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6538 @*/
6539 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6540 {
6541   IS              is, newis;
6542   const PetscInt *newRows;
6543 
6544   PetscFunctionBegin;
6545   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6546   PetscValidType(mat, 1);
6547   if (numRows) PetscValidIntPointer(rows, 3);
6548   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6549   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6550   MatCheckPreallocated(mat, 1);
6551 
6552   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6553   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6554   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6555   PetscCall(ISGetIndices(newis, &newRows));
6556   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6557   PetscCall(ISRestoreIndices(newis, &newRows));
6558   PetscCall(ISDestroy(&newis));
6559   PetscCall(ISDestroy(&is));
6560   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6561   PetscFunctionReturn(PETSC_SUCCESS);
6562 }
6563 
6564 /*@
6565    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6566    of a set of rows and columns of a matrix; using local numbering of rows.
6567 
6568    Collective
6569 
6570    Input Parameters:
6571 +  mat - the matrix
6572 .  is - index set of rows to remove
6573 .  diag - value put in all diagonals of eliminated rows
6574 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6575 -  b - optional vector of right hand side, that will be adjusted by provided solution
6576 
6577    Level: intermediate
6578 
6579    Notes:
6580    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6581    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6582 
6583    See `MatZeroRowsColumns()` for details on how this routine operates.
6584 
6585 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6586           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6587 @*/
6588 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6589 {
6590   PetscInt        numRows;
6591   const PetscInt *rows;
6592 
6593   PetscFunctionBegin;
6594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6595   PetscValidType(mat, 1);
6596   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6597   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6598   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6599   MatCheckPreallocated(mat, 1);
6600 
6601   PetscCall(ISGetLocalSize(is, &numRows));
6602   PetscCall(ISGetIndices(is, &rows));
6603   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6604   PetscCall(ISRestoreIndices(is, &rows));
6605   PetscFunctionReturn(PETSC_SUCCESS);
6606 }
6607 
6608 /*@C
6609    MatGetSize - Returns the numbers of rows and columns in a matrix.
6610 
6611    Not Collective
6612 
6613    Input Parameter:
6614 .  mat - the matrix
6615 
6616    Output Parameters:
6617 +  m - the number of global rows
6618 -  n - the number of global columns
6619 
6620    Level: beginner
6621 
6622    Note:
6623    Both output parameters can be `NULL` on input.
6624 
6625 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6626 @*/
6627 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6628 {
6629   PetscFunctionBegin;
6630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6631   if (m) *m = mat->rmap->N;
6632   if (n) *n = mat->cmap->N;
6633   PetscFunctionReturn(PETSC_SUCCESS);
6634 }
6635 
6636 /*@C
6637    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6638    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6639 
6640    Not Collective
6641 
6642    Input Parameter:
6643 .  mat - the matrix
6644 
6645    Output Parameters:
6646 +  m - the number of local rows, use `NULL` to not obtain this value
6647 -  n - the number of local columns, use `NULL` to not obtain this value
6648 
6649    Level: beginner
6650 
6651 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6652 @*/
6653 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6654 {
6655   PetscFunctionBegin;
6656   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6657   if (m) PetscValidIntPointer(m, 2);
6658   if (n) PetscValidIntPointer(n, 3);
6659   if (m) *m = mat->rmap->n;
6660   if (n) *n = mat->cmap->n;
6661   PetscFunctionReturn(PETSC_SUCCESS);
6662 }
6663 
6664 /*@C
6665    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6666    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6667 
6668    Not Collective, unless matrix has not been allocated, then collective
6669 
6670    Input Parameter:
6671 .  mat - the matrix
6672 
6673    Output Parameters:
6674 +  m - the global index of the first local column, use `NULL` to not obtain this value
6675 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6676 
6677    Level: developer
6678 
6679 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6680 @*/
6681 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6682 {
6683   PetscFunctionBegin;
6684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6685   PetscValidType(mat, 1);
6686   if (m) PetscValidIntPointer(m, 2);
6687   if (n) PetscValidIntPointer(n, 3);
6688   MatCheckPreallocated(mat, 1);
6689   if (m) *m = mat->cmap->rstart;
6690   if (n) *n = mat->cmap->rend;
6691   PetscFunctionReturn(PETSC_SUCCESS);
6692 }
6693 
6694 /*@C
6695    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6696    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6697    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6698 
6699    Not Collective
6700 
6701    Input Parameter:
6702 .  mat - the matrix
6703 
6704    Output Parameters:
6705 +  m - the global index of the first local row, use `NULL` to not obtain this value
6706 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6707 
6708    Level: beginner
6709 
6710    Note:
6711   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6712   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6713   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6714 
6715 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6716           `PetscLayout`
6717 @*/
6718 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6719 {
6720   PetscFunctionBegin;
6721   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6722   PetscValidType(mat, 1);
6723   if (m) PetscValidIntPointer(m, 2);
6724   if (n) PetscValidIntPointer(n, 3);
6725   MatCheckPreallocated(mat, 1);
6726   if (m) *m = mat->rmap->rstart;
6727   if (n) *n = mat->rmap->rend;
6728   PetscFunctionReturn(PETSC_SUCCESS);
6729 }
6730 
6731 /*@C
6732    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6733    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
6734    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6735 
6736    Not Collective, unless matrix has not been allocated
6737 
6738    Input Parameter:
6739 .  mat - the matrix
6740 
6741    Output Parameter:
6742 .  ranges - start of each processors portion plus one more than the total length at the end
6743 
6744    Level: beginner
6745 
6746 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6747 @*/
6748 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6749 {
6750   PetscFunctionBegin;
6751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6752   PetscValidType(mat, 1);
6753   MatCheckPreallocated(mat, 1);
6754   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6755   PetscFunctionReturn(PETSC_SUCCESS);
6756 }
6757 
6758 /*@C
6759    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6760    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6761 
6762    Not Collective, unless matrix has not been allocated
6763 
6764    Input Parameter:
6765 .  mat - the matrix
6766 
6767    Output Parameter:
6768 .  ranges - start of each processors portion plus one more then the total length at the end
6769 
6770    Level: beginner
6771 
6772 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6773 @*/
6774 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6775 {
6776   PetscFunctionBegin;
6777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6778   PetscValidType(mat, 1);
6779   MatCheckPreallocated(mat, 1);
6780   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6781   PetscFunctionReturn(PETSC_SUCCESS);
6782 }
6783 
6784 /*@C
6785    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6786    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6787    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6788 
6789    Not Collective
6790 
6791    Input Parameter:
6792 .  A - matrix
6793 
6794    Output Parameters:
6795 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6796 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6797 
6798    Level: intermediate
6799 
6800 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6801 @*/
6802 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6803 {
6804   PetscErrorCode (*f)(Mat, IS *, IS *);
6805 
6806   PetscFunctionBegin;
6807   MatCheckPreallocated(A, 1);
6808   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6809   if (f) {
6810     PetscCall((*f)(A, rows, cols));
6811   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6812     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6813     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6814   }
6815   PetscFunctionReturn(PETSC_SUCCESS);
6816 }
6817 
6818 /*@C
6819    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6820    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6821    to complete the factorization.
6822 
6823    Collective
6824 
6825    Input Parameters:
6826 +  fact - the factorized matrix obtained with `MatGetFactor()`
6827 .  mat - the matrix
6828 .  row - row permutation
6829 .  col - column permutation
6830 -  info - structure containing
6831 .vb
6832       levels - number of levels of fill.
6833       expected fill - as ratio of original fill.
6834       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6835                 missing diagonal entries)
6836 .ve
6837 
6838    Level: developer
6839 
6840    Notes:
6841    See [Matrix Factorization](sec_matfactor) for additional information.
6842 
6843    Most users should employ the `KSP` interface for linear solvers
6844    instead of working directly with matrix algebra routines such as this.
6845    See, e.g., `KSPCreate()`.
6846 
6847    Uses the definition of level of fill as in Y. Saad, 2003
6848 
6849    Developer Note:
6850    The Fortran interface is not autogenerated as the
6851    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6852 
6853    References:
6854 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6855 
6856 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6857           `MatGetOrdering()`, `MatFactorInfo`
6858 @*/
6859 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6860 {
6861   PetscFunctionBegin;
6862   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6863   PetscValidType(mat, 2);
6864   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6865   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6866   PetscValidPointer(info, 5);
6867   PetscValidPointer(fact, 1);
6868   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6869   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6870   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6871   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6872   MatCheckPreallocated(mat, 2);
6873 
6874   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6875   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6876   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6877   PetscFunctionReturn(PETSC_SUCCESS);
6878 }
6879 
6880 /*@C
6881    MatICCFactorSymbolic - Performs symbolic incomplete
6882    Cholesky factorization for a symmetric matrix.  Use
6883    `MatCholeskyFactorNumeric()` to complete the factorization.
6884 
6885    Collective
6886 
6887    Input Parameters:
6888 +  fact - the factorized matrix obtained with `MatGetFactor()`
6889 .  mat - the matrix to be factored
6890 .  perm - row and column permutation
6891 -  info - structure containing
6892 .vb
6893       levels - number of levels of fill.
6894       expected fill - as ratio of original fill.
6895 .ve
6896 
6897    Level: developer
6898 
6899    Notes:
6900    Most users should employ the `KSP` interface for linear solvers
6901    instead of working directly with matrix algebra routines such as this.
6902    See, e.g., `KSPCreate()`.
6903 
6904    This uses the definition of level of fill as in Y. Saad, 2003
6905 
6906    Developer Note:
6907    The Fortran interface is not autogenerated as the
6908    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6909 
6910    References:
6911 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6912 
6913 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6914 @*/
6915 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6916 {
6917   PetscFunctionBegin;
6918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6919   PetscValidType(mat, 2);
6920   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6921   PetscValidPointer(info, 4);
6922   PetscValidPointer(fact, 1);
6923   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6924   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6925   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6926   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6927   MatCheckPreallocated(mat, 2);
6928 
6929   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6930   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6931   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6932   PetscFunctionReturn(PETSC_SUCCESS);
6933 }
6934 
6935 /*@C
6936    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6937    points to an array of valid matrices, they may be reused to store the new
6938    submatrices.
6939 
6940    Collective
6941 
6942    Input Parameters:
6943 +  mat - the matrix
6944 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6945 .  irow - index set of rows to extract
6946 .  icol - index set of columns to extract
6947 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6948 
6949    Output Parameter:
6950 .  submat - the array of submatrices
6951 
6952    Level: advanced
6953 
6954    Notes:
6955    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6956    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6957    to extract a parallel submatrix.
6958 
6959    Some matrix types place restrictions on the row and column
6960    indices, such as that they be sorted or that they be equal to each other.
6961 
6962    The index sets may not have duplicate entries.
6963 
6964    When extracting submatrices from a parallel matrix, each processor can
6965    form a different submatrix by setting the rows and columns of its
6966    individual index sets according to the local submatrix desired.
6967 
6968    When finished using the submatrices, the user should destroy
6969    them with `MatDestroySubMatrices()`.
6970 
6971    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6972    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6973 
6974    This routine creates the matrices in submat; you should NOT create them before
6975    calling it. It also allocates the array of matrix pointers submat.
6976 
6977    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6978    request one row/column in a block, they must request all rows/columns that are in
6979    that block. For example, if the block size is 2 you cannot request just row 0 and
6980    column 0.
6981 
6982    Fortran Note:
6983    The Fortran interface is slightly different from that given below; it
6984    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6985 
6986 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6987 @*/
6988 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6989 {
6990   PetscInt  i;
6991   PetscBool eq;
6992 
6993   PetscFunctionBegin;
6994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6995   PetscValidType(mat, 1);
6996   if (n) {
6997     PetscValidPointer(irow, 3);
6998     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6999     PetscValidPointer(icol, 4);
7000     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7001   }
7002   PetscValidPointer(submat, 6);
7003   if (n && scall == MAT_REUSE_MATRIX) {
7004     PetscValidPointer(*submat, 6);
7005     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7006   }
7007   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7008   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7009   MatCheckPreallocated(mat, 1);
7010   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7011   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7012   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7013   for (i = 0; i < n; i++) {
7014     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7015     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7016     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7017 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7018     if (mat->boundtocpu && mat->bindingpropagates) {
7019       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7020       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7021     }
7022 #endif
7023   }
7024   PetscFunctionReturn(PETSC_SUCCESS);
7025 }
7026 
7027 /*@C
7028    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7029 
7030    Collective
7031 
7032    Input Parameters:
7033 +  mat - the matrix
7034 .  n   - the number of submatrixes to be extracted
7035 .  irow - index set of rows to extract
7036 .  icol - index set of columns to extract
7037 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7038 
7039    Output Parameter:
7040 .  submat - the array of submatrices
7041 
7042    Level: advanced
7043 
7044    Note:
7045    This is used by `PCGASM`
7046 
7047 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7048 @*/
7049 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7050 {
7051   PetscInt  i;
7052   PetscBool eq;
7053 
7054   PetscFunctionBegin;
7055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7056   PetscValidType(mat, 1);
7057   if (n) {
7058     PetscValidPointer(irow, 3);
7059     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7060     PetscValidPointer(icol, 4);
7061     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7062   }
7063   PetscValidPointer(submat, 6);
7064   if (n && scall == MAT_REUSE_MATRIX) {
7065     PetscValidPointer(*submat, 6);
7066     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7067   }
7068   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7069   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7070   MatCheckPreallocated(mat, 1);
7071 
7072   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7073   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7074   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7075   for (i = 0; i < n; i++) {
7076     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7077     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7078   }
7079   PetscFunctionReturn(PETSC_SUCCESS);
7080 }
7081 
7082 /*@C
7083    MatDestroyMatrices - Destroys an array of matrices.
7084 
7085    Collective
7086 
7087    Input Parameters:
7088 +  n - the number of local matrices
7089 -  mat - the matrices (this is a pointer to the array of matrices)
7090 
7091    Level: advanced
7092 
7093     Note:
7094     Frees not only the matrices, but also the array that contains the matrices
7095 
7096     Fortran Note:
7097     This does not free the array.
7098 
7099 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7100 @*/
7101 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7102 {
7103   PetscInt i;
7104 
7105   PetscFunctionBegin;
7106   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7107   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7108   PetscValidPointer(mat, 2);
7109 
7110   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7111 
7112   /* memory is allocated even if n = 0 */
7113   PetscCall(PetscFree(*mat));
7114   PetscFunctionReturn(PETSC_SUCCESS);
7115 }
7116 
7117 /*@C
7118    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7119 
7120    Collective
7121 
7122    Input Parameters:
7123 +  n - the number of local matrices
7124 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7125                        sequence of `MatCreateSubMatrices()`)
7126 
7127    Level: advanced
7128 
7129     Note:
7130     Frees not only the matrices, but also the array that contains the matrices
7131 
7132     Fortran Note:
7133     This does not free the array.
7134 
7135 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7136 @*/
7137 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7138 {
7139   Mat mat0;
7140 
7141   PetscFunctionBegin;
7142   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7143   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7144   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7145   PetscValidPointer(mat, 2);
7146 
7147   mat0 = (*mat)[0];
7148   if (mat0 && mat0->ops->destroysubmatrices) {
7149     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7150   } else {
7151     PetscCall(MatDestroyMatrices(n, mat));
7152   }
7153   PetscFunctionReturn(PETSC_SUCCESS);
7154 }
7155 
7156 /*@C
7157    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7158 
7159    Collective
7160 
7161    Input Parameter:
7162 .  mat - the matrix
7163 
7164    Output Parameter:
7165 .  matstruct - the sequential matrix with the nonzero structure of mat
7166 
7167   Level: developer
7168 
7169 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7170 @*/
7171 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7172 {
7173   PetscFunctionBegin;
7174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7175   PetscValidPointer(matstruct, 2);
7176 
7177   PetscValidType(mat, 1);
7178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7179   MatCheckPreallocated(mat, 1);
7180 
7181   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7182   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7183   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7184   PetscFunctionReturn(PETSC_SUCCESS);
7185 }
7186 
7187 /*@C
7188    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7189 
7190    Collective
7191 
7192    Input Parameter:
7193 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7194                        sequence of `MatGetSeqNonzeroStructure()`)
7195 
7196    Level: advanced
7197 
7198     Note:
7199     Frees not only the matrices, but also the array that contains the matrices
7200 
7201 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7202 @*/
7203 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7204 {
7205   PetscFunctionBegin;
7206   PetscValidPointer(mat, 1);
7207   PetscCall(MatDestroy(mat));
7208   PetscFunctionReturn(PETSC_SUCCESS);
7209 }
7210 
7211 /*@
7212    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7213    replaces the index sets by larger ones that represent submatrices with
7214    additional overlap.
7215 
7216    Collective
7217 
7218    Input Parameters:
7219 +  mat - the matrix
7220 .  n   - the number of index sets
7221 .  is  - the array of index sets (these index sets will changed during the call)
7222 -  ov  - the additional overlap requested
7223 
7224    Options Database Key:
7225 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7226 
7227    Level: developer
7228 
7229    Note:
7230    The computed overlap preserves the matrix block sizes when the blocks are square.
7231    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7232    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7233 
7234 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7235 @*/
7236 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7237 {
7238   PetscInt i, bs, cbs;
7239 
7240   PetscFunctionBegin;
7241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7242   PetscValidType(mat, 1);
7243   PetscValidLogicalCollectiveInt(mat, n, 2);
7244   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7245   if (n) {
7246     PetscValidPointer(is, 3);
7247     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7248   }
7249   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7250   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7251   MatCheckPreallocated(mat, 1);
7252 
7253   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7254   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7255   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7256   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7257   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7258   if (bs == cbs) {
7259     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7260   }
7261   PetscFunctionReturn(PETSC_SUCCESS);
7262 }
7263 
7264 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7265 
7266 /*@
7267    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7268    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7269    additional overlap.
7270 
7271    Collective
7272 
7273    Input Parameters:
7274 +  mat - the matrix
7275 .  n   - the number of index sets
7276 .  is  - the array of index sets (these index sets will changed during the call)
7277 -  ov  - the additional overlap requested
7278 
7279 `   Options Database Key:
7280 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7281 
7282    Level: developer
7283 
7284 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7285 @*/
7286 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7287 {
7288   PetscInt i;
7289 
7290   PetscFunctionBegin;
7291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7292   PetscValidType(mat, 1);
7293   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7294   if (n) {
7295     PetscValidPointer(is, 3);
7296     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7297   }
7298   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7299   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7300   MatCheckPreallocated(mat, 1);
7301   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7302   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7303   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7304   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7305   PetscFunctionReturn(PETSC_SUCCESS);
7306 }
7307 
7308 /*@
7309    MatGetBlockSize - Returns the matrix block size.
7310 
7311    Not Collective
7312 
7313    Input Parameter:
7314 .  mat - the matrix
7315 
7316    Output Parameter:
7317 .  bs - block size
7318 
7319    Level: intermediate
7320 
7321    Notes:
7322     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7323 
7324    If the block size has not been set yet this routine returns 1.
7325 
7326 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7327 @*/
7328 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7329 {
7330   PetscFunctionBegin;
7331   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7332   PetscValidIntPointer(bs, 2);
7333   *bs = PetscAbs(mat->rmap->bs);
7334   PetscFunctionReturn(PETSC_SUCCESS);
7335 }
7336 
7337 /*@
7338    MatGetBlockSizes - Returns the matrix block row and column sizes.
7339 
7340    Not Collective
7341 
7342    Input Parameter:
7343 .  mat - the matrix
7344 
7345    Output Parameters:
7346 +  rbs - row block size
7347 -  cbs - column block size
7348 
7349    Level: intermediate
7350 
7351    Notes:
7352     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7353     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7354 
7355    If a block size has not been set yet this routine returns 1.
7356 
7357 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7358 @*/
7359 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7360 {
7361   PetscFunctionBegin;
7362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7363   if (rbs) PetscValidIntPointer(rbs, 2);
7364   if (cbs) PetscValidIntPointer(cbs, 3);
7365   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7366   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7367   PetscFunctionReturn(PETSC_SUCCESS);
7368 }
7369 
7370 /*@
7371    MatSetBlockSize - Sets the matrix block size.
7372 
7373    Logically Collective
7374 
7375    Input Parameters:
7376 +  mat - the matrix
7377 -  bs - block size
7378 
7379    Level: intermediate
7380 
7381    Notes:
7382     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7383     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7384 
7385     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7386     is compatible with the matrix local sizes.
7387 
7388 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7389 @*/
7390 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7391 {
7392   PetscFunctionBegin;
7393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7394   PetscValidLogicalCollectiveInt(mat, bs, 2);
7395   PetscCall(MatSetBlockSizes(mat, bs, bs));
7396   PetscFunctionReturn(PETSC_SUCCESS);
7397 }
7398 
7399 typedef struct {
7400   PetscInt         n;
7401   IS              *is;
7402   Mat             *mat;
7403   PetscObjectState nonzerostate;
7404   Mat              C;
7405 } EnvelopeData;
7406 
7407 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7408 {
7409   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7410   PetscCall(PetscFree(edata->is));
7411   PetscCall(PetscFree(edata));
7412   return PETSC_SUCCESS;
7413 }
7414 
7415 /*
7416    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7417          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7418 
7419    Collective
7420 
7421    Input Parameter:
7422 .  mat - the matrix
7423 
7424    Notes:
7425      There can be zeros within the blocks
7426 
7427      The blocks can overlap between processes, including laying on more than two processes
7428 
7429 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7430 */
7431 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7432 {
7433   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7434   PetscInt          *diag, *odiag, sc;
7435   VecScatter         scatter;
7436   PetscScalar       *seqv;
7437   const PetscScalar *parv;
7438   const PetscInt    *ia, *ja;
7439   PetscBool          set, flag, done;
7440   Mat                AA = mat, A;
7441   MPI_Comm           comm;
7442   PetscMPIInt        rank, size, tag;
7443   MPI_Status         status;
7444   PetscContainer     container;
7445   EnvelopeData      *edata;
7446   Vec                seq, par;
7447   IS                 isglobal;
7448 
7449   PetscFunctionBegin;
7450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7451   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7452   if (!set || !flag) {
7453     /* TOO: only needs nonzero structure of transpose */
7454     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7455     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7456   }
7457   PetscCall(MatAIJGetLocalMat(AA, &A));
7458   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7459   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7460 
7461   PetscCall(MatGetLocalSize(mat, &n, NULL));
7462   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7463   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7464   PetscCallMPI(MPI_Comm_size(comm, &size));
7465   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7466 
7467   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7468 
7469   if (rank > 0) {
7470     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7471     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7472   }
7473   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7474   for (i = 0; i < n; i++) {
7475     env = PetscMax(env, ja[ia[i + 1] - 1]);
7476     II  = rstart + i;
7477     if (env == II) {
7478       starts[lblocks]  = tbs;
7479       sizes[lblocks++] = 1 + II - tbs;
7480       tbs              = 1 + II;
7481     }
7482   }
7483   if (rank < size - 1) {
7484     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7485     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7486   }
7487 
7488   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7489   if (!set || !flag) PetscCall(MatDestroy(&AA));
7490   PetscCall(MatDestroy(&A));
7491 
7492   PetscCall(PetscNew(&edata));
7493   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7494   edata->n = lblocks;
7495   /* create IS needed for extracting blocks from the original matrix */
7496   PetscCall(PetscMalloc1(lblocks, &edata->is));
7497   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7498 
7499   /* Create the resulting inverse matrix structure with preallocation information */
7500   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7501   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7502   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7503   PetscCall(MatSetType(edata->C, MATAIJ));
7504 
7505   /* Communicate the start and end of each row, from each block to the correct rank */
7506   /* TODO: Use PetscSF instead of VecScatter */
7507   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7508   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7509   PetscCall(VecGetArrayWrite(seq, &seqv));
7510   for (PetscInt i = 0; i < lblocks; i++) {
7511     for (PetscInt j = 0; j < sizes[i]; j++) {
7512       seqv[cnt]     = starts[i];
7513       seqv[cnt + 1] = starts[i] + sizes[i];
7514       cnt += 2;
7515     }
7516   }
7517   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7518   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7519   sc -= cnt;
7520   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7521   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7522   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7523   PetscCall(ISDestroy(&isglobal));
7524   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7525   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7526   PetscCall(VecScatterDestroy(&scatter));
7527   PetscCall(VecDestroy(&seq));
7528   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7529   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7530   PetscCall(VecGetArrayRead(par, &parv));
7531   cnt = 0;
7532   PetscCall(MatGetSize(mat, NULL, &n));
7533   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7534     PetscInt start, end, d = 0, od = 0;
7535 
7536     start = (PetscInt)PetscRealPart(parv[cnt]);
7537     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7538     cnt += 2;
7539 
7540     if (start < cstart) {
7541       od += cstart - start + n - cend;
7542       d += cend - cstart;
7543     } else if (start < cend) {
7544       od += n - cend;
7545       d += cend - start;
7546     } else od += n - start;
7547     if (end <= cstart) {
7548       od -= cstart - end + n - cend;
7549       d -= cend - cstart;
7550     } else if (end < cend) {
7551       od -= n - cend;
7552       d -= cend - end;
7553     } else od -= n - end;
7554 
7555     odiag[i] = od;
7556     diag[i]  = d;
7557   }
7558   PetscCall(VecRestoreArrayRead(par, &parv));
7559   PetscCall(VecDestroy(&par));
7560   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7561   PetscCall(PetscFree2(diag, odiag));
7562   PetscCall(PetscFree2(sizes, starts));
7563 
7564   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7565   PetscCall(PetscContainerSetPointer(container, edata));
7566   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7567   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7568   PetscCall(PetscObjectDereference((PetscObject)container));
7569   PetscFunctionReturn(PETSC_SUCCESS);
7570 }
7571 
7572 /*@
7573   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7574 
7575   Collective
7576 
7577   Input Parameters:
7578 + A - the matrix
7579 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7580 
7581   Output Parameter:
7582 . C - matrix with inverted block diagonal of `A`
7583 
7584   Level: advanced
7585 
7586   Note:
7587      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7588 
7589 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7590 @*/
7591 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7592 {
7593   PetscContainer   container;
7594   EnvelopeData    *edata;
7595   PetscObjectState nonzerostate;
7596 
7597   PetscFunctionBegin;
7598   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7599   if (!container) {
7600     PetscCall(MatComputeVariableBlockEnvelope(A));
7601     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7602   }
7603   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7604   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7605   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7606   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7607 
7608   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7609   *C = edata->C;
7610 
7611   for (PetscInt i = 0; i < edata->n; i++) {
7612     Mat          D;
7613     PetscScalar *dvalues;
7614 
7615     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7616     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7617     PetscCall(MatSeqDenseInvert(D));
7618     PetscCall(MatDenseGetArray(D, &dvalues));
7619     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7620     PetscCall(MatDestroy(&D));
7621   }
7622   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7623   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7624   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7625   PetscFunctionReturn(PETSC_SUCCESS);
7626 }
7627 
7628 /*@
7629    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7630 
7631    Logically Collective
7632 
7633    Input Parameters:
7634 +  mat - the matrix
7635 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7636 -  bsizes - the block sizes
7637 
7638    Level: intermediate
7639 
7640    Notes:
7641     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7642 
7643     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.
7644 
7645 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7646           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7647 @*/
7648 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7649 {
7650   PetscInt i, ncnt = 0, nlocal;
7651 
7652   PetscFunctionBegin;
7653   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7654   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7655   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7656   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7657   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);
7658   PetscCall(PetscFree(mat->bsizes));
7659   mat->nblocks = nblocks;
7660   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7661   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7662   PetscFunctionReturn(PETSC_SUCCESS);
7663 }
7664 
7665 /*@C
7666    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7667 
7668    Logically Collective; No Fortran Support
7669 
7670    Input Parameter:
7671 .  mat - the matrix
7672 
7673    Output Parameters:
7674 +  nblocks - the number of blocks on this process
7675 -  bsizes - the block sizes
7676 
7677    Level: intermediate
7678 
7679 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7680 @*/
7681 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7682 {
7683   PetscFunctionBegin;
7684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7685   *nblocks = mat->nblocks;
7686   *bsizes  = mat->bsizes;
7687   PetscFunctionReturn(PETSC_SUCCESS);
7688 }
7689 
7690 /*@
7691    MatSetBlockSizes - Sets the matrix block row and column sizes.
7692 
7693    Logically Collective
7694 
7695    Input Parameters:
7696 +  mat - the matrix
7697 .  rbs - row block size
7698 -  cbs - column block size
7699 
7700    Level: intermediate
7701 
7702    Notes:
7703     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7704     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7705     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7706 
7707     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7708     are compatible with the matrix local sizes.
7709 
7710     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7711 
7712 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7713 @*/
7714 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7715 {
7716   PetscFunctionBegin;
7717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7718   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7719   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7720   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7721   if (mat->rmap->refcnt) {
7722     ISLocalToGlobalMapping l2g  = NULL;
7723     PetscLayout            nmap = NULL;
7724 
7725     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7726     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7727     PetscCall(PetscLayoutDestroy(&mat->rmap));
7728     mat->rmap          = nmap;
7729     mat->rmap->mapping = l2g;
7730   }
7731   if (mat->cmap->refcnt) {
7732     ISLocalToGlobalMapping l2g  = NULL;
7733     PetscLayout            nmap = NULL;
7734 
7735     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7736     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7737     PetscCall(PetscLayoutDestroy(&mat->cmap));
7738     mat->cmap          = nmap;
7739     mat->cmap->mapping = l2g;
7740   }
7741   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7742   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7743   PetscFunctionReturn(PETSC_SUCCESS);
7744 }
7745 
7746 /*@
7747    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7748 
7749    Logically Collective
7750 
7751    Input Parameters:
7752 +  mat - the matrix
7753 .  fromRow - matrix from which to copy row block size
7754 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7755 
7756    Level: developer
7757 
7758 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7759 @*/
7760 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7761 {
7762   PetscFunctionBegin;
7763   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7764   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7765   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7766   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7767   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7768   PetscFunctionReturn(PETSC_SUCCESS);
7769 }
7770 
7771 /*@
7772    MatResidual - Default routine to calculate the residual r = b - Ax
7773 
7774    Collective
7775 
7776    Input Parameters:
7777 +  mat - the matrix
7778 .  b   - the right-hand-side
7779 -  x   - the approximate solution
7780 
7781    Output Parameter:
7782 .  r - location to store the residual
7783 
7784    Level: developer
7785 
7786 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7787 @*/
7788 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7789 {
7790   PetscFunctionBegin;
7791   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7792   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7793   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7794   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7795   PetscValidType(mat, 1);
7796   MatCheckPreallocated(mat, 1);
7797   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7798   if (!mat->ops->residual) {
7799     PetscCall(MatMult(mat, x, r));
7800     PetscCall(VecAYPX(r, -1.0, b));
7801   } else {
7802     PetscUseTypeMethod(mat, residual, b, x, r);
7803   }
7804   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7805   PetscFunctionReturn(PETSC_SUCCESS);
7806 }
7807 
7808 /*MC
7809     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7810 
7811     Synopsis:
7812     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7813 
7814     Not Collective
7815 
7816     Input Parameters:
7817 +   A - the matrix
7818 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7819 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7820 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7821                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7822                  always used.
7823 
7824     Output Parameters:
7825 +   n - number of local rows in the (possibly compressed) matrix
7826 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7827 .   ja - the column indices
7828 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7829            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7830 
7831     Level: developer
7832 
7833     Note:
7834     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7835 
7836 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7837 M*/
7838 
7839 /*MC
7840     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7841 
7842     Synopsis:
7843     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7844 
7845     Not Collective
7846 
7847     Input Parameters:
7848 +   A - the  matrix
7849 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7850 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7851     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7852                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7853                  always used.
7854 .   n - number of local rows in the (possibly compressed) matrix
7855 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7856 .   ja - the column indices
7857 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7858            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7859 
7860     Level: developer
7861 
7862 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7863 M*/
7864 
7865 /*@C
7866     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7867 
7868    Collective
7869 
7870     Input Parameters:
7871 +   mat - the matrix
7872 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7873 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7874 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7875                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7876                  always used.
7877 
7878     Output Parameters:
7879 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7880 .   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
7881 .   ja - the column indices, use `NULL` if not needed
7882 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7883            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7884 
7885     Level: developer
7886 
7887     Notes:
7888     You CANNOT change any of the ia[] or ja[] values.
7889 
7890     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7891 
7892     Fortran Notes:
7893     Use
7894 .vb
7895     PetscInt, pointer :: ia(:),ja(:)
7896     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7897     ! Access the ith and jth entries via ia(i) and ja(j)
7898 .ve
7899    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7900 
7901 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7902 @*/
7903 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7904 {
7905   PetscFunctionBegin;
7906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7907   PetscValidType(mat, 1);
7908   if (n) PetscValidIntPointer(n, 5);
7909   if (ia) PetscValidPointer(ia, 6);
7910   if (ja) PetscValidPointer(ja, 7);
7911   if (done) PetscValidBoolPointer(done, 8);
7912   MatCheckPreallocated(mat, 1);
7913   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7914   else {
7915     if (done) *done = PETSC_TRUE;
7916     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7917     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7918     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7919   }
7920   PetscFunctionReturn(PETSC_SUCCESS);
7921 }
7922 
7923 /*@C
7924     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7925 
7926     Collective
7927 
7928     Input Parameters:
7929 +   mat - the matrix
7930 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7931 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7932                 symmetrized
7933 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7934                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7935                  always used.
7936 .   n - number of columns in the (possibly compressed) matrix
7937 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7938 -   ja - the row indices
7939 
7940     Output Parameter:
7941 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7942 
7943     Level: developer
7944 
7945 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7946 @*/
7947 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7948 {
7949   PetscFunctionBegin;
7950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7951   PetscValidType(mat, 1);
7952   PetscValidIntPointer(n, 5);
7953   if (ia) PetscValidPointer(ia, 6);
7954   if (ja) PetscValidPointer(ja, 7);
7955   PetscValidBoolPointer(done, 8);
7956   MatCheckPreallocated(mat, 1);
7957   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7958   else {
7959     *done = PETSC_TRUE;
7960     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7961   }
7962   PetscFunctionReturn(PETSC_SUCCESS);
7963 }
7964 
7965 /*@C
7966     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7967 
7968     Collective
7969 
7970     Input Parameters:
7971 +   mat - the matrix
7972 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7973 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7974 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7975                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7976                  always used.
7977 .   n - size of (possibly compressed) matrix
7978 .   ia - the row pointers
7979 -   ja - the column indices
7980 
7981     Output Parameter:
7982 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7983 
7984     Level: developer
7985 
7986     Note:
7987     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7988     us of the array after it has been restored. If you pass `NULL`, it will
7989     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7990 
7991     Fortran Note:
7992    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
7993 
7994 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
7995 @*/
7996 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7997 {
7998   PetscFunctionBegin;
7999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8000   PetscValidType(mat, 1);
8001   if (ia) PetscValidPointer(ia, 6);
8002   if (ja) PetscValidPointer(ja, 7);
8003   if (done) PetscValidBoolPointer(done, 8);
8004   MatCheckPreallocated(mat, 1);
8005 
8006   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8007   else {
8008     if (done) *done = PETSC_TRUE;
8009     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8010     if (n) *n = 0;
8011     if (ia) *ia = NULL;
8012     if (ja) *ja = NULL;
8013   }
8014   PetscFunctionReturn(PETSC_SUCCESS);
8015 }
8016 
8017 /*@C
8018     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8019 
8020     Collective
8021 
8022     Input Parameters:
8023 +   mat - the matrix
8024 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8025 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8026 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8027                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8028                  always used.
8029 
8030     Output Parameters:
8031 +   n - size of (possibly compressed) matrix
8032 .   ia - the column pointers
8033 .   ja - the row indices
8034 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8035 
8036     Level: developer
8037 
8038 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8039 @*/
8040 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8041 {
8042   PetscFunctionBegin;
8043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8044   PetscValidType(mat, 1);
8045   if (ia) PetscValidPointer(ia, 6);
8046   if (ja) PetscValidPointer(ja, 7);
8047   PetscValidBoolPointer(done, 8);
8048   MatCheckPreallocated(mat, 1);
8049 
8050   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8051   else {
8052     *done = PETSC_TRUE;
8053     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8054     if (n) *n = 0;
8055     if (ia) *ia = NULL;
8056     if (ja) *ja = NULL;
8057   }
8058   PetscFunctionReturn(PETSC_SUCCESS);
8059 }
8060 
8061 /*@C
8062     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8063 
8064     Collective
8065 
8066     Input Parameters:
8067 +   mat - the matrix
8068 .   ncolors - maximum color value
8069 .   n   - number of entries in colorarray
8070 -   colorarray - array indicating color for each column
8071 
8072     Output Parameter:
8073 .   iscoloring - coloring generated using colorarray information
8074 
8075     Level: developer
8076 
8077 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8078 @*/
8079 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8080 {
8081   PetscFunctionBegin;
8082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8083   PetscValidType(mat, 1);
8084   PetscValidIntPointer(colorarray, 4);
8085   PetscValidPointer(iscoloring, 5);
8086   MatCheckPreallocated(mat, 1);
8087 
8088   if (!mat->ops->coloringpatch) {
8089     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8090   } else {
8091     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8092   }
8093   PetscFunctionReturn(PETSC_SUCCESS);
8094 }
8095 
8096 /*@
8097    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8098 
8099    Logically Collective
8100 
8101    Input Parameter:
8102 .  mat - the factored matrix to be reset
8103 
8104    Level: developer
8105 
8106    Notes:
8107    This routine should be used only with factored matrices formed by in-place
8108    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8109    format).  This option can save memory, for example, when solving nonlinear
8110    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8111    ILU(0) preconditioner.
8112 
8113    One can specify in-place ILU(0) factorization by calling
8114 .vb
8115      PCType(pc,PCILU);
8116      PCFactorSeUseInPlace(pc);
8117 .ve
8118    or by using the options -pc_type ilu -pc_factor_in_place
8119 
8120    In-place factorization ILU(0) can also be used as a local
8121    solver for the blocks within the block Jacobi or additive Schwarz
8122    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8123    for details on setting local solver options.
8124 
8125    Most users should employ the `KSP` interface for linear solvers
8126    instead of working directly with matrix algebra routines such as this.
8127    See, e.g., `KSPCreate()`.
8128 
8129 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8130 @*/
8131 PetscErrorCode MatSetUnfactored(Mat mat)
8132 {
8133   PetscFunctionBegin;
8134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8135   PetscValidType(mat, 1);
8136   MatCheckPreallocated(mat, 1);
8137   mat->factortype = MAT_FACTOR_NONE;
8138   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8139   PetscUseTypeMethod(mat, setunfactored);
8140   PetscFunctionReturn(PETSC_SUCCESS);
8141 }
8142 
8143 /*MC
8144     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8145 
8146     Synopsis:
8147     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8148 
8149     Not Collective
8150 
8151     Input Parameter:
8152 .   x - matrix
8153 
8154     Output Parameters:
8155 +   xx_v - the Fortran pointer to the array
8156 -   ierr - error code
8157 
8158     Example of Usage:
8159 .vb
8160       PetscScalar, pointer xx_v(:,:)
8161       ....
8162       call MatDenseGetArrayF90(x,xx_v,ierr)
8163       a = xx_v(3)
8164       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8165 .ve
8166 
8167     Level: advanced
8168 
8169 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8170 M*/
8171 
8172 /*MC
8173     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8174     accessed with `MatDenseGetArrayF90()`.
8175 
8176     Synopsis:
8177     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8178 
8179     Not Collective
8180 
8181     Input Parameters:
8182 +   x - matrix
8183 -   xx_v - the Fortran90 pointer to the array
8184 
8185     Output Parameter:
8186 .   ierr - error code
8187 
8188     Example of Usage:
8189 .vb
8190        PetscScalar, pointer xx_v(:,:)
8191        ....
8192        call MatDenseGetArrayF90(x,xx_v,ierr)
8193        a = xx_v(3)
8194        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8195 .ve
8196 
8197     Level: advanced
8198 
8199 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8200 M*/
8201 
8202 /*MC
8203     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8204 
8205     Synopsis:
8206     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8207 
8208     Not Collective
8209 
8210     Input Parameter:
8211 .   x - matrix
8212 
8213     Output Parameters:
8214 +   xx_v - the Fortran pointer to the array
8215 -   ierr - error code
8216 
8217     Example of Usage:
8218 .vb
8219       PetscScalar, pointer xx_v(:)
8220       ....
8221       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8222       a = xx_v(3)
8223       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8224 .ve
8225 
8226     Level: advanced
8227 
8228 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8229 M*/
8230 
8231 /*MC
8232     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8233     accessed with `MatSeqAIJGetArrayF90()`.
8234 
8235     Synopsis:
8236     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8237 
8238     Not Collective
8239 
8240     Input Parameters:
8241 +   x - matrix
8242 -   xx_v - the Fortran90 pointer to the array
8243 
8244     Output Parameter:
8245 .   ierr - error code
8246 
8247     Example of Usage:
8248 .vb
8249        PetscScalar, pointer xx_v(:)
8250        ....
8251        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8252        a = xx_v(3)
8253        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8254 .ve
8255 
8256     Level: advanced
8257 
8258 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8259 M*/
8260 
8261 /*@
8262     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8263                       as the original matrix.
8264 
8265     Collective
8266 
8267     Input Parameters:
8268 +   mat - the original matrix
8269 .   isrow - parallel `IS` containing the rows this processor should obtain
8270 .   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.
8271 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8272 
8273     Output Parameter:
8274 .   newmat - the new submatrix, of the same type as the original matrix
8275 
8276     Level: advanced
8277 
8278     Notes:
8279     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8280 
8281     Some matrix types place restrictions on the row and column indices, such
8282     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;
8283     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8284 
8285     The index sets may not have duplicate entries.
8286 
8287       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8288    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8289    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8290    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8291    you are finished using it.
8292 
8293     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8294     the input matrix.
8295 
8296     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8297 
8298    Example usage:
8299    Consider the following 8x8 matrix with 34 non-zero values, that is
8300    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8301    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8302    as follows
8303 .vb
8304             1  2  0  |  0  3  0  |  0  4
8305     Proc0   0  5  6  |  7  0  0  |  8  0
8306             9  0 10  | 11  0  0  | 12  0
8307     -------------------------------------
8308            13  0 14  | 15 16 17  |  0  0
8309     Proc1   0 18  0  | 19 20 21  |  0  0
8310             0  0  0  | 22 23  0  | 24  0
8311     -------------------------------------
8312     Proc2  25 26 27  |  0  0 28  | 29  0
8313            30  0  0  | 31 32 33  |  0 34
8314 .ve
8315 
8316     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8317 
8318 .vb
8319             2  0  |  0  3  0  |  0
8320     Proc0   5  6  |  7  0  0  |  8
8321     -------------------------------
8322     Proc1  18  0  | 19 20 21  |  0
8323     -------------------------------
8324     Proc2  26 27  |  0  0 28  | 29
8325             0  0  | 31 32 33  |  0
8326 .ve
8327 
8328 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8329 @*/
8330 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8331 {
8332   PetscMPIInt size;
8333   Mat        *local;
8334   IS          iscoltmp;
8335   PetscBool   flg;
8336 
8337   PetscFunctionBegin;
8338   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8339   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8340   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8341   PetscValidPointer(newmat, 5);
8342   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8343   PetscValidType(mat, 1);
8344   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8345   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8346 
8347   MatCheckPreallocated(mat, 1);
8348   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8349 
8350   if (!iscol || isrow == iscol) {
8351     PetscBool   stride;
8352     PetscMPIInt grabentirematrix = 0, grab;
8353     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8354     if (stride) {
8355       PetscInt first, step, n, rstart, rend;
8356       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8357       if (step == 1) {
8358         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8359         if (rstart == first) {
8360           PetscCall(ISGetLocalSize(isrow, &n));
8361           if (n == rend - rstart) grabentirematrix = 1;
8362         }
8363       }
8364     }
8365     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8366     if (grab) {
8367       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8368       if (cll == MAT_INITIAL_MATRIX) {
8369         *newmat = mat;
8370         PetscCall(PetscObjectReference((PetscObject)mat));
8371       }
8372       PetscFunctionReturn(PETSC_SUCCESS);
8373     }
8374   }
8375 
8376   if (!iscol) {
8377     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8378   } else {
8379     iscoltmp = iscol;
8380   }
8381 
8382   /* if original matrix is on just one processor then use submatrix generated */
8383   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8384     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8385     goto setproperties;
8386   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8387     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8388     *newmat = *local;
8389     PetscCall(PetscFree(local));
8390     goto setproperties;
8391   } else if (!mat->ops->createsubmatrix) {
8392     /* Create a new matrix type that implements the operation using the full matrix */
8393     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8394     switch (cll) {
8395     case MAT_INITIAL_MATRIX:
8396       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8397       break;
8398     case MAT_REUSE_MATRIX:
8399       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8400       break;
8401     default:
8402       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8403     }
8404     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8405     goto setproperties;
8406   }
8407 
8408   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8409   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8410   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8411 
8412 setproperties:
8413   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8414   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8415   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8416   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8417   PetscFunctionReturn(PETSC_SUCCESS);
8418 }
8419 
8420 /*@
8421    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8422 
8423    Not Collective
8424 
8425    Input Parameters:
8426 +  A - the matrix we wish to propagate options from
8427 -  B - the matrix we wish to propagate options to
8428 
8429    Level: beginner
8430 
8431    Note:
8432    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8433 
8434 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8435 @*/
8436 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8437 {
8438   PetscFunctionBegin;
8439   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8440   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8441   B->symmetry_eternal            = A->symmetry_eternal;
8442   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8443   B->symmetric                   = A->symmetric;
8444   B->structurally_symmetric      = A->structurally_symmetric;
8445   B->spd                         = A->spd;
8446   B->hermitian                   = A->hermitian;
8447   PetscFunctionReturn(PETSC_SUCCESS);
8448 }
8449 
8450 /*@
8451    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8452    used during the assembly process to store values that belong to
8453    other processors.
8454 
8455    Not Collective
8456 
8457    Input Parameters:
8458 +  mat   - the matrix
8459 .  size  - the initial size of the stash.
8460 -  bsize - the initial size of the block-stash(if used).
8461 
8462    Options Database Keys:
8463 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8464 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8465 
8466    Level: intermediate
8467 
8468    Notes:
8469      The block-stash is used for values set with `MatSetValuesBlocked()` while
8470      the stash is used for values set with `MatSetValues()`
8471 
8472      Run with the option -info and look for output of the form
8473      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8474      to determine the appropriate value, MM, to use for size and
8475      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8476      to determine the value, BMM to use for bsize
8477 
8478 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8479 @*/
8480 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8481 {
8482   PetscFunctionBegin;
8483   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8484   PetscValidType(mat, 1);
8485   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8486   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8487   PetscFunctionReturn(PETSC_SUCCESS);
8488 }
8489 
8490 /*@
8491    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8492      the matrix
8493 
8494    Neighbor-wise Collective
8495 
8496    Input Parameters:
8497 +  mat   - the matrix
8498 .  x - the vector to be multiplied by the interpolation operator
8499 -  y - the vector to be added to the result
8500 
8501    Output Parameter:
8502 .  w - the resulting vector
8503 
8504    Level: intermediate
8505 
8506    Notes:
8507     `w` may be the same vector as `y`.
8508 
8509     This allows one to use either the restriction or interpolation (its transpose)
8510     matrix to do the interpolation
8511 
8512 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8513 @*/
8514 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8515 {
8516   PetscInt M, N, Ny;
8517 
8518   PetscFunctionBegin;
8519   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8520   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8521   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8522   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8523   PetscCall(MatGetSize(A, &M, &N));
8524   PetscCall(VecGetSize(y, &Ny));
8525   if (M == Ny) {
8526     PetscCall(MatMultAdd(A, x, y, w));
8527   } else {
8528     PetscCall(MatMultTransposeAdd(A, x, y, w));
8529   }
8530   PetscFunctionReturn(PETSC_SUCCESS);
8531 }
8532 
8533 /*@
8534    MatInterpolate - 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 interpolated
8542 
8543    Output Parameter:
8544 .  y - the resulting vector
8545 
8546    Level: intermediate
8547 
8548    Note:
8549     This allows one to use either the restriction or interpolation (its transpose)
8550     matrix to do the interpolation
8551 
8552 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8553 @*/
8554 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8555 {
8556   PetscInt M, N, Ny;
8557 
8558   PetscFunctionBegin;
8559   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8560   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8561   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8562   PetscCall(MatGetSize(A, &M, &N));
8563   PetscCall(VecGetSize(y, &Ny));
8564   if (M == Ny) {
8565     PetscCall(MatMult(A, x, y));
8566   } else {
8567     PetscCall(MatMultTranspose(A, x, y));
8568   }
8569   PetscFunctionReturn(PETSC_SUCCESS);
8570 }
8571 
8572 /*@
8573    MatRestrict - y = A*x or A'*x
8574 
8575    Neighbor-wise Collective
8576 
8577    Input Parameters:
8578 +  mat   - the matrix
8579 -  x - the vector to be restricted
8580 
8581    Output Parameter:
8582 .  y - the resulting vector
8583 
8584    Level: intermediate
8585 
8586    Note:
8587     This allows one to use either the restriction or interpolation (its transpose)
8588     matrix to do the restriction
8589 
8590 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8591 @*/
8592 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8593 {
8594   PetscInt M, N, Ny;
8595 
8596   PetscFunctionBegin;
8597   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8598   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8599   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8600   PetscCall(MatGetSize(A, &M, &N));
8601   PetscCall(VecGetSize(y, &Ny));
8602   if (M == Ny) {
8603     PetscCall(MatMult(A, x, y));
8604   } else {
8605     PetscCall(MatMultTranspose(A, x, y));
8606   }
8607   PetscFunctionReturn(PETSC_SUCCESS);
8608 }
8609 
8610 /*@
8611    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8612 
8613    Neighbor-wise Collective
8614 
8615    Input Parameters:
8616 +  mat   - the matrix
8617 .  x - the input dense matrix to be multiplied
8618 -  w - the input dense matrix to be added to the result
8619 
8620    Output Parameter:
8621 .  y - the output dense matrix
8622 
8623    Level: intermediate
8624 
8625    Note:
8626     This allows one to use either the restriction or interpolation (its transpose)
8627     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8628     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8629 
8630 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8631 @*/
8632 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8633 {
8634   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8635   PetscBool trans = PETSC_TRUE;
8636   MatReuse  reuse = MAT_INITIAL_MATRIX;
8637 
8638   PetscFunctionBegin;
8639   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8640   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8641   PetscValidType(x, 2);
8642   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8643   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8644   PetscCall(MatGetSize(A, &M, &N));
8645   PetscCall(MatGetSize(x, &Mx, &Nx));
8646   if (N == Mx) trans = PETSC_FALSE;
8647   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);
8648   Mo = trans ? N : M;
8649   if (*y) {
8650     PetscCall(MatGetSize(*y, &My, &Ny));
8651     if (Mo == My && Nx == Ny) {
8652       reuse = MAT_REUSE_MATRIX;
8653     } else {
8654       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);
8655       PetscCall(MatDestroy(y));
8656     }
8657   }
8658 
8659   if (w && *y == w) { /* this is to minimize changes in PCMG */
8660     PetscBool flg;
8661 
8662     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8663     if (w) {
8664       PetscInt My, Ny, Mw, Nw;
8665 
8666       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8667       PetscCall(MatGetSize(*y, &My, &Ny));
8668       PetscCall(MatGetSize(w, &Mw, &Nw));
8669       if (!flg || My != Mw || Ny != Nw) w = NULL;
8670     }
8671     if (!w) {
8672       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8673       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8674       PetscCall(PetscObjectDereference((PetscObject)w));
8675     } else {
8676       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8677     }
8678   }
8679   if (!trans) {
8680     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8681   } else {
8682     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8683   }
8684   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8685   PetscFunctionReturn(PETSC_SUCCESS);
8686 }
8687 
8688 /*@
8689    MatMatInterpolate - Y = A*X or A'*X
8690 
8691    Neighbor-wise Collective
8692 
8693    Input Parameters:
8694 +  mat   - the matrix
8695 -  x - the input dense matrix
8696 
8697    Output Parameter:
8698 .  y - the output dense matrix
8699 
8700    Level: intermediate
8701 
8702    Note:
8703     This allows one to use either the restriction or interpolation (its transpose)
8704     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8705     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8706 
8707 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8708 @*/
8709 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8710 {
8711   PetscFunctionBegin;
8712   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8713   PetscFunctionReturn(PETSC_SUCCESS);
8714 }
8715 
8716 /*@
8717    MatMatRestrict - Y = A*X or A'*X
8718 
8719    Neighbor-wise Collective
8720 
8721    Input Parameters:
8722 +  mat   - the matrix
8723 -  x - the input dense matrix
8724 
8725    Output Parameter:
8726 .  y - the output dense matrix
8727 
8728    Level: intermediate
8729 
8730    Note:
8731     This allows one to use either the restriction or interpolation (its transpose)
8732     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8733     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8734 
8735 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8736 @*/
8737 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8738 {
8739   PetscFunctionBegin;
8740   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8741   PetscFunctionReturn(PETSC_SUCCESS);
8742 }
8743 
8744 /*@
8745    MatGetNullSpace - retrieves the null space of a matrix.
8746 
8747    Logically Collective
8748 
8749    Input Parameters:
8750 +  mat - the matrix
8751 -  nullsp - the null space object
8752 
8753    Level: developer
8754 
8755 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8756 @*/
8757 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8758 {
8759   PetscFunctionBegin;
8760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8761   PetscValidPointer(nullsp, 2);
8762   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8763   PetscFunctionReturn(PETSC_SUCCESS);
8764 }
8765 
8766 /*@
8767    MatSetNullSpace - attaches a null space to a matrix.
8768 
8769    Logically Collective
8770 
8771    Input Parameters:
8772 +  mat - the matrix
8773 -  nullsp - the null space object
8774 
8775    Level: advanced
8776 
8777    Notes:
8778       This null space is used by the `KSP` linear solvers to solve singular systems.
8779 
8780       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`
8781 
8782       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
8783       to zero but the linear system will still be solved in a least squares sense.
8784 
8785       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8786    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).
8787    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
8788    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
8789    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).
8790    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8791 
8792     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8793     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8794     routine also automatically calls `MatSetTransposeNullSpace()`.
8795 
8796     The user should call `MatNullSpaceDestroy()`.
8797 
8798 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8799           `KSPSetPCSide()`
8800 @*/
8801 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8802 {
8803   PetscFunctionBegin;
8804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8805   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8806   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8807   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8808   mat->nullsp = nullsp;
8809   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8810   PetscFunctionReturn(PETSC_SUCCESS);
8811 }
8812 
8813 /*@
8814    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8815 
8816    Logically Collective
8817 
8818    Input Parameters:
8819 +  mat - the matrix
8820 -  nullsp - the null space object
8821 
8822    Level: developer
8823 
8824 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8825 @*/
8826 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8827 {
8828   PetscFunctionBegin;
8829   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8830   PetscValidType(mat, 1);
8831   PetscValidPointer(nullsp, 2);
8832   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8833   PetscFunctionReturn(PETSC_SUCCESS);
8834 }
8835 
8836 /*@
8837    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8838 
8839    Logically Collective
8840 
8841    Input Parameters:
8842 +  mat - the matrix
8843 -  nullsp - the null space object
8844 
8845    Level: advanced
8846 
8847    Notes:
8848    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8849 
8850    See `MatSetNullSpace()`
8851 
8852 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8853 @*/
8854 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8855 {
8856   PetscFunctionBegin;
8857   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8858   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8859   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8860   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8861   mat->transnullsp = nullsp;
8862   PetscFunctionReturn(PETSC_SUCCESS);
8863 }
8864 
8865 /*@
8866    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8867         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8868 
8869    Logically Collective
8870 
8871    Input Parameters:
8872 +  mat - the matrix
8873 -  nullsp - the null space object
8874 
8875    Level: advanced
8876 
8877    Notes:
8878    Overwrites any previous near null space that may have been attached
8879 
8880    You can remove the null space by calling this routine with an nullsp of `NULL`
8881 
8882 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8883 @*/
8884 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8885 {
8886   PetscFunctionBegin;
8887   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8888   PetscValidType(mat, 1);
8889   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8890   MatCheckPreallocated(mat, 1);
8891   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8892   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8893   mat->nearnullsp = nullsp;
8894   PetscFunctionReturn(PETSC_SUCCESS);
8895 }
8896 
8897 /*@
8898    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8899 
8900    Not Collective
8901 
8902    Input Parameter:
8903 .  mat - the matrix
8904 
8905    Output Parameter:
8906 .  nullsp - the null space object, `NULL` if not set
8907 
8908    Level: advanced
8909 
8910 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8911 @*/
8912 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8913 {
8914   PetscFunctionBegin;
8915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8916   PetscValidType(mat, 1);
8917   PetscValidPointer(nullsp, 2);
8918   MatCheckPreallocated(mat, 1);
8919   *nullsp = mat->nearnullsp;
8920   PetscFunctionReturn(PETSC_SUCCESS);
8921 }
8922 
8923 /*@C
8924    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8925 
8926    Collective
8927 
8928    Input Parameters:
8929 +  mat - the matrix
8930 .  row - row/column permutation
8931 -  info - information on desired factorization process
8932 
8933    Level: developer
8934 
8935    Notes:
8936    Probably really in-place only when level of fill is zero, otherwise allocates
8937    new space to store factored matrix and deletes previous memory.
8938 
8939    Most users should employ the `KSP` interface for linear solvers
8940    instead of working directly with matrix algebra routines such as this.
8941    See, e.g., `KSPCreate()`.
8942 
8943    Developer Note:
8944    The Fortran interface is not autogenerated as the
8945    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8946 
8947 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8948 @*/
8949 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8950 {
8951   PetscFunctionBegin;
8952   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8953   PetscValidType(mat, 1);
8954   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8955   PetscValidPointer(info, 3);
8956   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8957   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8958   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8959   MatCheckPreallocated(mat, 1);
8960   PetscUseTypeMethod(mat, iccfactor, row, info);
8961   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8962   PetscFunctionReturn(PETSC_SUCCESS);
8963 }
8964 
8965 /*@
8966    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8967          ghosted ones.
8968 
8969    Not Collective
8970 
8971    Input Parameters:
8972 +  mat - the matrix
8973 -  diag - the diagonal values, including ghost ones
8974 
8975    Level: developer
8976 
8977    Notes:
8978     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8979 
8980     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8981 
8982 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8983 @*/
8984 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8985 {
8986   PetscMPIInt size;
8987 
8988   PetscFunctionBegin;
8989   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8990   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8991   PetscValidType(mat, 1);
8992 
8993   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8994   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8995   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8996   if (size == 1) {
8997     PetscInt n, m;
8998     PetscCall(VecGetSize(diag, &n));
8999     PetscCall(MatGetSize(mat, NULL, &m));
9000     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9001     PetscCall(MatDiagonalScale(mat, NULL, diag));
9002   } else {
9003     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9004   }
9005   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9006   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9007   PetscFunctionReturn(PETSC_SUCCESS);
9008 }
9009 
9010 /*@
9011    MatGetInertia - Gets the inertia from a factored matrix
9012 
9013    Collective
9014 
9015    Input Parameter:
9016 .  mat - the matrix
9017 
9018    Output Parameters:
9019 +   nneg - number of negative eigenvalues
9020 .   nzero - number of zero eigenvalues
9021 -   npos - number of positive eigenvalues
9022 
9023    Level: advanced
9024 
9025    Note:
9026     Matrix must have been factored by `MatCholeskyFactor()`
9027 
9028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9029 @*/
9030 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9031 {
9032   PetscFunctionBegin;
9033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9034   PetscValidType(mat, 1);
9035   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9036   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9037   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9038   PetscFunctionReturn(PETSC_SUCCESS);
9039 }
9040 
9041 /*@C
9042    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9043 
9044    Neighbor-wise Collective
9045 
9046    Input Parameters:
9047 +  mat - the factored matrix obtained with `MatGetFactor()`
9048 -  b - the right-hand-side vectors
9049 
9050    Output Parameter:
9051 .  x - the result vectors
9052 
9053    Level: developer
9054 
9055    Note:
9056    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9057    call `MatSolves`(A,x,x).
9058 
9059 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9060 @*/
9061 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9062 {
9063   PetscFunctionBegin;
9064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9065   PetscValidType(mat, 1);
9066   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9067   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9068   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9069 
9070   MatCheckPreallocated(mat, 1);
9071   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9072   PetscUseTypeMethod(mat, solves, b, x);
9073   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9074   PetscFunctionReturn(PETSC_SUCCESS);
9075 }
9076 
9077 /*@
9078    MatIsSymmetric - Test whether a matrix is symmetric
9079 
9080    Collective
9081 
9082    Input Parameters:
9083 +  A - the matrix to test
9084 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9085 
9086    Output Parameter:
9087 .  flg - the result
9088 
9089    Level: intermediate
9090 
9091    Notes:
9092     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9093 
9094     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9095 
9096     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9097     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9098 
9099 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9100           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9101 @*/
9102 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9103 {
9104   PetscFunctionBegin;
9105   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9106   PetscValidBoolPointer(flg, 3);
9107 
9108   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9109   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9110   else {
9111     PetscUseTypeMethod(A, issymmetric, tol, flg);
9112     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9113   }
9114   PetscFunctionReturn(PETSC_SUCCESS);
9115 }
9116 
9117 /*@
9118    MatIsHermitian - Test whether a matrix is Hermitian
9119 
9120    Collective
9121 
9122    Input Parameters:
9123 +  A - the matrix to test
9124 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9125 
9126    Output Parameter:
9127 .  flg - the result
9128 
9129    Level: intermediate
9130 
9131    Notes:
9132     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9133 
9134     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9135 
9136     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9137     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9138 
9139 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9140           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9141 @*/
9142 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9143 {
9144   PetscFunctionBegin;
9145   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9146   PetscValidBoolPointer(flg, 3);
9147 
9148   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9149   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9150   else {
9151     PetscUseTypeMethod(A, ishermitian, tol, flg);
9152     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9153   }
9154   PetscFunctionReturn(PETSC_SUCCESS);
9155 }
9156 
9157 /*@
9158    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9159 
9160    Not Collective
9161 
9162    Input Parameter:
9163 .  A - the matrix to check
9164 
9165    Output Parameters:
9166 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9167 -  flg - the result (only valid if set is `PETSC_TRUE`)
9168 
9169    Level: advanced
9170 
9171    Notes:
9172    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9173    if you want it explicitly checked
9174 
9175     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9176     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9177 
9178 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9179 @*/
9180 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9181 {
9182   PetscFunctionBegin;
9183   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9184   PetscValidBoolPointer(set, 2);
9185   PetscValidBoolPointer(flg, 3);
9186   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9187     *set = PETSC_TRUE;
9188     *flg = PetscBool3ToBool(A->symmetric);
9189   } else {
9190     *set = PETSC_FALSE;
9191   }
9192   PetscFunctionReturn(PETSC_SUCCESS);
9193 }
9194 
9195 /*@
9196    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9197 
9198    Not Collective
9199 
9200    Input Parameter:
9201 .  A - the matrix to check
9202 
9203    Output Parameters:
9204 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9205 -  flg - the result (only valid if set is `PETSC_TRUE`)
9206 
9207    Level: advanced
9208 
9209    Notes:
9210    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9211 
9212    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9213    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9214 
9215 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9216 @*/
9217 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9218 {
9219   PetscFunctionBegin;
9220   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9221   PetscValidBoolPointer(set, 2);
9222   PetscValidBoolPointer(flg, 3);
9223   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9224     *set = PETSC_TRUE;
9225     *flg = PetscBool3ToBool(A->spd);
9226   } else {
9227     *set = PETSC_FALSE;
9228   }
9229   PetscFunctionReturn(PETSC_SUCCESS);
9230 }
9231 
9232 /*@
9233    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9234 
9235    Not Collective
9236 
9237    Input Parameter:
9238 .  A - the matrix to check
9239 
9240    Output Parameters:
9241 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9242 -  flg - the result (only valid if set is `PETSC_TRUE`)
9243 
9244    Level: advanced
9245 
9246    Notes:
9247    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9248    if you want it explicitly checked
9249 
9250    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9251    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9252 
9253 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9254 @*/
9255 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9256 {
9257   PetscFunctionBegin;
9258   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9259   PetscValidBoolPointer(set, 2);
9260   PetscValidBoolPointer(flg, 3);
9261   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9262     *set = PETSC_TRUE;
9263     *flg = PetscBool3ToBool(A->hermitian);
9264   } else {
9265     *set = PETSC_FALSE;
9266   }
9267   PetscFunctionReturn(PETSC_SUCCESS);
9268 }
9269 
9270 /*@
9271    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9272 
9273    Collective
9274 
9275    Input Parameter:
9276 .  A - the matrix to test
9277 
9278    Output Parameter:
9279 .  flg - the result
9280 
9281    Level: intermediate
9282 
9283    Notes:
9284    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9285 
9286    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
9287    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9288 
9289 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9290 @*/
9291 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9292 {
9293   PetscFunctionBegin;
9294   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9295   PetscValidBoolPointer(flg, 2);
9296   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9297     *flg = PetscBool3ToBool(A->structurally_symmetric);
9298   } else {
9299     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9300     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9301   }
9302   PetscFunctionReturn(PETSC_SUCCESS);
9303 }
9304 
9305 /*@
9306    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9307 
9308    Not Collective
9309 
9310    Input Parameter:
9311 .  A - the matrix to check
9312 
9313    Output Parameters:
9314 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9315 -  flg - the result (only valid if set is PETSC_TRUE)
9316 
9317    Level: advanced
9318 
9319    Notes:
9320    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
9321    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9322 
9323    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9324 
9325 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9326 @*/
9327 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9328 {
9329   PetscFunctionBegin;
9330   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9331   PetscValidBoolPointer(set, 2);
9332   PetscValidBoolPointer(flg, 3);
9333   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9334     *set = PETSC_TRUE;
9335     *flg = PetscBool3ToBool(A->structurally_symmetric);
9336   } else {
9337     *set = PETSC_FALSE;
9338   }
9339   PetscFunctionReturn(PETSC_SUCCESS);
9340 }
9341 
9342 /*@
9343    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9344        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9345 
9346     Not Collective
9347 
9348    Input Parameter:
9349 .   mat - the matrix
9350 
9351    Output Parameters:
9352 +   nstash   - the size of the stash
9353 .   reallocs - the number of additional mallocs incurred.
9354 .   bnstash   - the size of the block stash
9355 -   breallocs - the number of additional mallocs incurred.in the block stash
9356 
9357    Level: advanced
9358 
9359 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9360 @*/
9361 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9362 {
9363   PetscFunctionBegin;
9364   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9365   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9366   PetscFunctionReturn(PETSC_SUCCESS);
9367 }
9368 
9369 /*@C
9370    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9371    parallel layout, `PetscLayout` for rows and columns
9372 
9373    Collective
9374 
9375    Input Parameter:
9376 .  mat - the matrix
9377 
9378    Output Parameters:
9379 +   right - (optional) vector that the matrix can be multiplied against
9380 -   left - (optional) vector that the matrix vector product can be stored in
9381 
9382   Level: advanced
9383 
9384    Notes:
9385     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()`.
9386 
9387     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9388 
9389 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9390 @*/
9391 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9392 {
9393   PetscFunctionBegin;
9394   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9395   PetscValidType(mat, 1);
9396   if (mat->ops->getvecs) {
9397     PetscUseTypeMethod(mat, getvecs, right, left);
9398   } else {
9399     PetscInt rbs, cbs;
9400     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9401     if (right) {
9402       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9403       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9404       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9405       PetscCall(VecSetBlockSize(*right, cbs));
9406       PetscCall(VecSetType(*right, mat->defaultvectype));
9407 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9408       if (mat->boundtocpu && mat->bindingpropagates) {
9409         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9410         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9411       }
9412 #endif
9413       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9414     }
9415     if (left) {
9416       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9417       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9418       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9419       PetscCall(VecSetBlockSize(*left, rbs));
9420       PetscCall(VecSetType(*left, mat->defaultvectype));
9421 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9422       if (mat->boundtocpu && mat->bindingpropagates) {
9423         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9424         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9425       }
9426 #endif
9427       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9428     }
9429   }
9430   PetscFunctionReturn(PETSC_SUCCESS);
9431 }
9432 
9433 /*@C
9434    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9435      with default values.
9436 
9437    Not Collective
9438 
9439    Input Parameter:
9440 .    info - the `MatFactorInfo` data structure
9441 
9442    Level: developer
9443 
9444    Notes:
9445     The solvers are generally used through the `KSP` and `PC` objects, for example
9446           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9447 
9448     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9449 
9450    Developer Note:
9451    The Fortran interface is not autogenerated as the
9452    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9453 
9454 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9455 @*/
9456 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9457 {
9458   PetscFunctionBegin;
9459   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9460   PetscFunctionReturn(PETSC_SUCCESS);
9461 }
9462 
9463 /*@
9464    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9465 
9466    Collective
9467 
9468    Input Parameters:
9469 +  mat - the factored matrix
9470 -  is - the index set defining the Schur indices (0-based)
9471 
9472    Level: advanced
9473 
9474    Notes:
9475     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9476 
9477    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9478 
9479    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9480 
9481 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9482           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9483 @*/
9484 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9485 {
9486   PetscErrorCode (*f)(Mat, IS);
9487 
9488   PetscFunctionBegin;
9489   PetscValidType(mat, 1);
9490   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9491   PetscValidType(is, 2);
9492   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9493   PetscCheckSameComm(mat, 1, is, 2);
9494   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9495   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9496   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9497   PetscCall(MatDestroy(&mat->schur));
9498   PetscCall((*f)(mat, is));
9499   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9500   PetscFunctionReturn(PETSC_SUCCESS);
9501 }
9502 
9503 /*@
9504   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9505 
9506    Logically Collective
9507 
9508    Input Parameters:
9509 +  F - the factored matrix obtained by calling `MatGetFactor()`
9510 .  S - location where to return the Schur complement, can be `NULL`
9511 -  status - the status of the Schur complement matrix, can be `NULL`
9512 
9513    Level: advanced
9514 
9515    Notes:
9516    You must call `MatFactorSetSchurIS()` before calling this routine.
9517 
9518    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9519 
9520    The routine provides a copy of the Schur matrix stored within the solver data structures.
9521    The caller must destroy the object when it is no longer needed.
9522    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9523 
9524    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)
9525 
9526    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9527 
9528    Developer Note:
9529     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9530    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9531 
9532 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9533 @*/
9534 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9535 {
9536   PetscFunctionBegin;
9537   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9538   if (S) PetscValidPointer(S, 2);
9539   if (status) PetscValidPointer(status, 3);
9540   if (S) {
9541     PetscErrorCode (*f)(Mat, Mat *);
9542 
9543     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9544     if (f) {
9545       PetscCall((*f)(F, S));
9546     } else {
9547       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9548     }
9549   }
9550   if (status) *status = F->schur_status;
9551   PetscFunctionReturn(PETSC_SUCCESS);
9552 }
9553 
9554 /*@
9555   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9556 
9557    Logically Collective
9558 
9559    Input Parameters:
9560 +  F - the factored matrix obtained by calling `MatGetFactor()`
9561 .  *S - location where to return the Schur complement, can be `NULL`
9562 -  status - the status of the Schur complement matrix, can be `NULL`
9563 
9564    Level: advanced
9565 
9566    Notes:
9567    You must call `MatFactorSetSchurIS()` before calling this routine.
9568 
9569    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9570 
9571    The routine returns a the Schur Complement stored within the data structures of the solver.
9572 
9573    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9574 
9575    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9576 
9577    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9578 
9579    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9580 
9581 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9582 @*/
9583 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9584 {
9585   PetscFunctionBegin;
9586   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9587   if (S) PetscValidPointer(S, 2);
9588   if (status) PetscValidPointer(status, 3);
9589   if (S) *S = F->schur;
9590   if (status) *status = F->schur_status;
9591   PetscFunctionReturn(PETSC_SUCCESS);
9592 }
9593 
9594 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9595 {
9596   Mat S = F->schur;
9597 
9598   PetscFunctionBegin;
9599   switch (F->schur_status) {
9600   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9601   case MAT_FACTOR_SCHUR_INVERTED:
9602     if (S) {
9603       S->ops->solve             = NULL;
9604       S->ops->matsolve          = NULL;
9605       S->ops->solvetranspose    = NULL;
9606       S->ops->matsolvetranspose = NULL;
9607       S->ops->solveadd          = NULL;
9608       S->ops->solvetransposeadd = NULL;
9609       S->factortype             = MAT_FACTOR_NONE;
9610       PetscCall(PetscFree(S->solvertype));
9611     }
9612   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9613     break;
9614   default:
9615     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9616   }
9617   PetscFunctionReturn(PETSC_SUCCESS);
9618 }
9619 
9620 /*@
9621   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9622 
9623    Logically Collective
9624 
9625    Input Parameters:
9626 +  F - the factored matrix obtained by calling `MatGetFactor()`
9627 .  *S - location where the Schur complement is stored
9628 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9629 
9630    Level: advanced
9631 
9632 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9633 @*/
9634 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9635 {
9636   PetscFunctionBegin;
9637   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9638   if (S) {
9639     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9640     *S = NULL;
9641   }
9642   F->schur_status = status;
9643   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9644   PetscFunctionReturn(PETSC_SUCCESS);
9645 }
9646 
9647 /*@
9648   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9649 
9650    Logically Collective
9651 
9652    Input Parameters:
9653 +  F - the factored matrix obtained by calling `MatGetFactor()`
9654 .  rhs - location where the right hand side of the Schur complement system is stored
9655 -  sol - location where the solution of the Schur complement system has to be returned
9656 
9657    Level: advanced
9658 
9659    Notes:
9660    The sizes of the vectors should match the size of the Schur complement
9661 
9662    Must be called after `MatFactorSetSchurIS()`
9663 
9664 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9665 @*/
9666 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9667 {
9668   PetscFunctionBegin;
9669   PetscValidType(F, 1);
9670   PetscValidType(rhs, 2);
9671   PetscValidType(sol, 3);
9672   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9673   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9674   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9675   PetscCheckSameComm(F, 1, rhs, 2);
9676   PetscCheckSameComm(F, 1, sol, 3);
9677   PetscCall(MatFactorFactorizeSchurComplement(F));
9678   switch (F->schur_status) {
9679   case MAT_FACTOR_SCHUR_FACTORED:
9680     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9681     break;
9682   case MAT_FACTOR_SCHUR_INVERTED:
9683     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9684     break;
9685   default:
9686     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9687   }
9688   PetscFunctionReturn(PETSC_SUCCESS);
9689 }
9690 
9691 /*@
9692   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9693 
9694    Logically Collective
9695 
9696    Input Parameters:
9697 +  F - the factored matrix obtained by calling `MatGetFactor()`
9698 .  rhs - location where the right hand side of the Schur complement system is stored
9699 -  sol - location where the solution of the Schur complement system has to be returned
9700 
9701    Level: advanced
9702 
9703    Notes:
9704    The sizes of the vectors should match the size of the Schur complement
9705 
9706    Must be called after `MatFactorSetSchurIS()`
9707 
9708 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9709 @*/
9710 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9711 {
9712   PetscFunctionBegin;
9713   PetscValidType(F, 1);
9714   PetscValidType(rhs, 2);
9715   PetscValidType(sol, 3);
9716   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9717   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9718   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9719   PetscCheckSameComm(F, 1, rhs, 2);
9720   PetscCheckSameComm(F, 1, sol, 3);
9721   PetscCall(MatFactorFactorizeSchurComplement(F));
9722   switch (F->schur_status) {
9723   case MAT_FACTOR_SCHUR_FACTORED:
9724     PetscCall(MatSolve(F->schur, rhs, sol));
9725     break;
9726   case MAT_FACTOR_SCHUR_INVERTED:
9727     PetscCall(MatMult(F->schur, rhs, sol));
9728     break;
9729   default:
9730     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9731   }
9732   PetscFunctionReturn(PETSC_SUCCESS);
9733 }
9734 
9735 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9736 #if PetscDefined(HAVE_CUDA)
9737 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9738 #endif
9739 
9740 /* Schur status updated in the interface */
9741 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9742 {
9743   Mat S = F->schur;
9744 
9745   PetscFunctionBegin;
9746   if (S) {
9747     PetscMPIInt size;
9748     PetscBool   isdense, isdensecuda;
9749 
9750     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9751     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9752     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9753     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9754     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9755     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9756     if (isdense) {
9757       PetscCall(MatSeqDenseInvertFactors_Private(S));
9758     } else if (isdensecuda) {
9759 #if defined(PETSC_HAVE_CUDA)
9760       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9761 #endif
9762     }
9763     // HIP??????????????
9764     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9765   }
9766   PetscFunctionReturn(PETSC_SUCCESS);
9767 }
9768 
9769 /*@
9770   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9771 
9772    Logically Collective
9773 
9774    Input Parameter:
9775 .  F - the factored matrix obtained by calling `MatGetFactor()`
9776 
9777    Level: advanced
9778 
9779    Notes:
9780     Must be called after `MatFactorSetSchurIS()`.
9781 
9782    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9783 
9784 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9785 @*/
9786 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9787 {
9788   PetscFunctionBegin;
9789   PetscValidType(F, 1);
9790   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9791   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9792   PetscCall(MatFactorFactorizeSchurComplement(F));
9793   PetscCall(MatFactorInvertSchurComplement_Private(F));
9794   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9795   PetscFunctionReturn(PETSC_SUCCESS);
9796 }
9797 
9798 /*@
9799   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9800 
9801    Logically Collective
9802 
9803    Input Parameter:
9804 .  F - the factored matrix obtained by calling `MatGetFactor()`
9805 
9806    Level: advanced
9807 
9808    Note:
9809     Must be called after `MatFactorSetSchurIS()`
9810 
9811 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9812 @*/
9813 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9814 {
9815   MatFactorInfo info;
9816 
9817   PetscFunctionBegin;
9818   PetscValidType(F, 1);
9819   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9820   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9821   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9822   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9823   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9824     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9825   } else {
9826     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9827   }
9828   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9829   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9830   PetscFunctionReturn(PETSC_SUCCESS);
9831 }
9832 
9833 /*@
9834    MatPtAP - Creates the matrix product C = P^T * A * P
9835 
9836    Neighbor-wise Collective
9837 
9838    Input Parameters:
9839 +  A - the matrix
9840 .  P - the projection matrix
9841 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9842 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9843           if the result is a dense matrix this is irrelevant
9844 
9845    Output Parameter:
9846 .  C - the product matrix
9847 
9848    Level: intermediate
9849 
9850    Notes:
9851    C will be created and must be destroyed by the user with `MatDestroy()`.
9852 
9853    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9854 
9855    Developer Note:
9856    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9857 
9858 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9859 @*/
9860 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9861 {
9862   PetscFunctionBegin;
9863   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9864   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9865 
9866   if (scall == MAT_INITIAL_MATRIX) {
9867     PetscCall(MatProductCreate(A, P, NULL, C));
9868     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9869     PetscCall(MatProductSetAlgorithm(*C, "default"));
9870     PetscCall(MatProductSetFill(*C, fill));
9871 
9872     (*C)->product->api_user = PETSC_TRUE;
9873     PetscCall(MatProductSetFromOptions(*C));
9874     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);
9875     PetscCall(MatProductSymbolic(*C));
9876   } else { /* scall == MAT_REUSE_MATRIX */
9877     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9878   }
9879 
9880   PetscCall(MatProductNumeric(*C));
9881   (*C)->symmetric = A->symmetric;
9882   (*C)->spd       = A->spd;
9883   PetscFunctionReturn(PETSC_SUCCESS);
9884 }
9885 
9886 /*@
9887    MatRARt - Creates the matrix product C = R * A * R^T
9888 
9889    Neighbor-wise Collective
9890 
9891    Input Parameters:
9892 +  A - the matrix
9893 .  R - the projection matrix
9894 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9895 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9896           if the result is a dense matrix this is irrelevant
9897 
9898    Output Parameter:
9899 .  C - the product matrix
9900 
9901    Level: intermediate
9902 
9903    Notes:
9904    C will be created and must be destroyed by the user with `MatDestroy()`.
9905 
9906    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9907 
9908    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9909    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9910    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9911    We recommend using MatPtAP().
9912 
9913 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9914 @*/
9915 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9916 {
9917   PetscFunctionBegin;
9918   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9919   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9920 
9921   if (scall == MAT_INITIAL_MATRIX) {
9922     PetscCall(MatProductCreate(A, R, NULL, C));
9923     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9924     PetscCall(MatProductSetAlgorithm(*C, "default"));
9925     PetscCall(MatProductSetFill(*C, fill));
9926 
9927     (*C)->product->api_user = PETSC_TRUE;
9928     PetscCall(MatProductSetFromOptions(*C));
9929     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);
9930     PetscCall(MatProductSymbolic(*C));
9931   } else { /* scall == MAT_REUSE_MATRIX */
9932     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9933   }
9934 
9935   PetscCall(MatProductNumeric(*C));
9936   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9937   PetscFunctionReturn(PETSC_SUCCESS);
9938 }
9939 
9940 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9941 {
9942   PetscFunctionBegin;
9943   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9944 
9945   if (scall == MAT_INITIAL_MATRIX) {
9946     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9947     PetscCall(MatProductCreate(A, B, NULL, C));
9948     PetscCall(MatProductSetType(*C, ptype));
9949     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9950     PetscCall(MatProductSetFill(*C, fill));
9951 
9952     (*C)->product->api_user = PETSC_TRUE;
9953     PetscCall(MatProductSetFromOptions(*C));
9954     PetscCall(MatProductSymbolic(*C));
9955   } else { /* scall == MAT_REUSE_MATRIX */
9956     Mat_Product *product = (*C)->product;
9957     PetscBool    isdense;
9958 
9959     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9960     if (isdense && product && product->type != ptype) {
9961       PetscCall(MatProductClear(*C));
9962       product = NULL;
9963     }
9964     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9965     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9966       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9967       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9968       product           = (*C)->product;
9969       product->fill     = fill;
9970       product->api_user = PETSC_TRUE;
9971       product->clear    = PETSC_TRUE;
9972 
9973       PetscCall(MatProductSetType(*C, ptype));
9974       PetscCall(MatProductSetFromOptions(*C));
9975       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);
9976       PetscCall(MatProductSymbolic(*C));
9977     } else { /* user may change input matrices A or B when REUSE */
9978       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9979     }
9980   }
9981   PetscCall(MatProductNumeric(*C));
9982   PetscFunctionReturn(PETSC_SUCCESS);
9983 }
9984 
9985 /*@
9986    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9987 
9988    Neighbor-wise Collective
9989 
9990    Input Parameters:
9991 +  A - the left matrix
9992 .  B - the right matrix
9993 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9994 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9995           if the result is a dense matrix this is irrelevant
9996 
9997    Output Parameter:
9998 .  C - the product matrix
9999 
10000    Notes:
10001    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10002 
10003    `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
10004    call to this function with `MAT_INITIAL_MATRIX`.
10005 
10006    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10007 
10008    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`,
10009    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10010 
10011    Example of Usage:
10012 .vb
10013      MatProductCreate(A,B,NULL,&C);
10014      MatProductSetType(C,MATPRODUCT_AB);
10015      MatProductSymbolic(C);
10016      MatProductNumeric(C); // compute C=A * B
10017      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10018      MatProductNumeric(C);
10019      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10020      MatProductNumeric(C);
10021 .ve
10022 
10023    Level: intermediate
10024 
10025 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10026 @*/
10027 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10028 {
10029   PetscFunctionBegin;
10030   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10031   PetscFunctionReturn(PETSC_SUCCESS);
10032 }
10033 
10034 /*@
10035    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10036 
10037    Neighbor-wise Collective
10038 
10039    Input Parameters:
10040 +  A - the left matrix
10041 .  B - the right matrix
10042 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10043 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10044 
10045    Output Parameter:
10046 .  C - the product matrix
10047 
10048    Level: intermediate
10049 
10050    Notes:
10051    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10052 
10053    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10054 
10055    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10056    actually needed.
10057 
10058    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10059    and for pairs of `MATMPIDENSE` matrices.
10060 
10061    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10062 
10063    Options Database Keys:
10064 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10065               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10066               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10067 
10068 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10069 @*/
10070 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10071 {
10072   PetscFunctionBegin;
10073   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10074   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10075   PetscFunctionReturn(PETSC_SUCCESS);
10076 }
10077 
10078 /*@
10079    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10080 
10081    Neighbor-wise Collective
10082 
10083    Input Parameters:
10084 +  A - the left matrix
10085 .  B - the right matrix
10086 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10087 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10088 
10089    Output Parameter:
10090 .  C - the product matrix
10091 
10092    Level: intermediate
10093 
10094    Notes:
10095    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10096 
10097    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10098 
10099    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10100 
10101    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10102    actually needed.
10103 
10104    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10105    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10106 
10107 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10108 @*/
10109 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10110 {
10111   PetscFunctionBegin;
10112   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10113   PetscFunctionReturn(PETSC_SUCCESS);
10114 }
10115 
10116 /*@
10117    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10118 
10119    Neighbor-wise Collective
10120 
10121    Input Parameters:
10122 +  A - the left matrix
10123 .  B - the middle matrix
10124 .  C - the right matrix
10125 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10126 -  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
10127           if the result is a dense matrix this is irrelevant
10128 
10129    Output Parameter:
10130 .  D - the product matrix
10131 
10132    Level: intermediate
10133 
10134    Notes:
10135    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10136 
10137    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10138 
10139    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10140 
10141    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10142    actually needed.
10143 
10144    If you have many matrices with the same non-zero structure to multiply, you
10145    should use `MAT_REUSE_MATRIX` in all calls but the first
10146 
10147 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10148 @*/
10149 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10150 {
10151   PetscFunctionBegin;
10152   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10153   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10154 
10155   if (scall == MAT_INITIAL_MATRIX) {
10156     PetscCall(MatProductCreate(A, B, C, D));
10157     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10158     PetscCall(MatProductSetAlgorithm(*D, "default"));
10159     PetscCall(MatProductSetFill(*D, fill));
10160 
10161     (*D)->product->api_user = PETSC_TRUE;
10162     PetscCall(MatProductSetFromOptions(*D));
10163     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,
10164                ((PetscObject)C)->type_name);
10165     PetscCall(MatProductSymbolic(*D));
10166   } else { /* user may change input matrices when REUSE */
10167     PetscCall(MatProductReplaceMats(A, B, C, *D));
10168   }
10169   PetscCall(MatProductNumeric(*D));
10170   PetscFunctionReturn(PETSC_SUCCESS);
10171 }
10172 
10173 /*@
10174    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10175 
10176    Collective
10177 
10178    Input Parameters:
10179 +  mat - the matrix
10180 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10181 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10182 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10183 
10184    Output Parameter:
10185 .  matredundant - redundant matrix
10186 
10187    Level: advanced
10188 
10189    Notes:
10190    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10191    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10192 
10193    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10194    calling it.
10195 
10196    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10197 
10198 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10199 @*/
10200 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10201 {
10202   MPI_Comm       comm;
10203   PetscMPIInt    size;
10204   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10205   Mat_Redundant *redund     = NULL;
10206   PetscSubcomm   psubcomm   = NULL;
10207   MPI_Comm       subcomm_in = subcomm;
10208   Mat           *matseq;
10209   IS             isrow, iscol;
10210   PetscBool      newsubcomm = PETSC_FALSE;
10211 
10212   PetscFunctionBegin;
10213   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10214   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10215     PetscValidPointer(*matredundant, 5);
10216     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10217   }
10218 
10219   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10220   if (size == 1 || nsubcomm == 1) {
10221     if (reuse == MAT_INITIAL_MATRIX) {
10222       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10223     } else {
10224       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");
10225       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10226     }
10227     PetscFunctionReturn(PETSC_SUCCESS);
10228   }
10229 
10230   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10231   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10232   MatCheckPreallocated(mat, 1);
10233 
10234   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10235   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10236     /* create psubcomm, then get subcomm */
10237     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10238     PetscCallMPI(MPI_Comm_size(comm, &size));
10239     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10240 
10241     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10242     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10243     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10244     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10245     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10246     newsubcomm = PETSC_TRUE;
10247     PetscCall(PetscSubcommDestroy(&psubcomm));
10248   }
10249 
10250   /* get isrow, iscol and a local sequential matrix matseq[0] */
10251   if (reuse == MAT_INITIAL_MATRIX) {
10252     mloc_sub = PETSC_DECIDE;
10253     nloc_sub = PETSC_DECIDE;
10254     if (bs < 1) {
10255       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10256       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10257     } else {
10258       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10259       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10260     }
10261     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10262     rstart = rend - mloc_sub;
10263     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10264     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10265   } else { /* reuse == MAT_REUSE_MATRIX */
10266     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");
10267     /* retrieve subcomm */
10268     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10269     redund = (*matredundant)->redundant;
10270     isrow  = redund->isrow;
10271     iscol  = redund->iscol;
10272     matseq = redund->matseq;
10273   }
10274   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10275 
10276   /* get matredundant over subcomm */
10277   if (reuse == MAT_INITIAL_MATRIX) {
10278     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10279 
10280     /* create a supporting struct and attach it to C for reuse */
10281     PetscCall(PetscNew(&redund));
10282     (*matredundant)->redundant = redund;
10283     redund->isrow              = isrow;
10284     redund->iscol              = iscol;
10285     redund->matseq             = matseq;
10286     if (newsubcomm) {
10287       redund->subcomm = subcomm;
10288     } else {
10289       redund->subcomm = MPI_COMM_NULL;
10290     }
10291   } else {
10292     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10293   }
10294 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10295   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10296     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10297     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10298   }
10299 #endif
10300   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10301   PetscFunctionReturn(PETSC_SUCCESS);
10302 }
10303 
10304 /*@C
10305    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10306    a given `Mat`. Each submatrix can span multiple procs.
10307 
10308    Collective
10309 
10310    Input Parameters:
10311 +  mat - the matrix
10312 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10313 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10314 
10315    Output Parameter:
10316 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10317 
10318   Level: advanced
10319 
10320   Notes:
10321   The submatrix partition across processors is dictated by `subComm` a
10322   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10323   is not restricted to be grouped with consecutive original ranks.
10324 
10325   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10326   map directly to the layout of the original matrix [wrt the local
10327   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10328   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10329   the `subMat`. However the offDiagMat looses some columns - and this is
10330   reconstructed with `MatSetValues()`
10331 
10332   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10333 
10334 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10335 @*/
10336 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10337 {
10338   PetscMPIInt commsize, subCommSize;
10339 
10340   PetscFunctionBegin;
10341   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10342   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10343   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10344 
10345   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");
10346   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10347   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10348   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10349   PetscFunctionReturn(PETSC_SUCCESS);
10350 }
10351 
10352 /*@
10353    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10354 
10355    Not Collective
10356 
10357    Input Parameters:
10358 +  mat - matrix to extract local submatrix from
10359 .  isrow - local row indices for submatrix
10360 -  iscol - local column indices for submatrix
10361 
10362    Output Parameter:
10363 .  submat - the submatrix
10364 
10365    Level: intermediate
10366 
10367    Notes:
10368    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10369 
10370    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10371    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10372 
10373    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10374    `MatSetValuesBlockedLocal()` will also be implemented.
10375 
10376    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10377    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10378 
10379 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10380 @*/
10381 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10382 {
10383   PetscFunctionBegin;
10384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10385   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10386   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10387   PetscCheckSameComm(isrow, 2, iscol, 3);
10388   PetscValidPointer(submat, 4);
10389   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10390 
10391   if (mat->ops->getlocalsubmatrix) {
10392     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10393   } else {
10394     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10395   }
10396   PetscFunctionReturn(PETSC_SUCCESS);
10397 }
10398 
10399 /*@
10400    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10401 
10402    Not Collective
10403 
10404    Input Parameters:
10405 +  mat - matrix to extract local submatrix from
10406 .  isrow - local row indices for submatrix
10407 .  iscol - local column indices for submatrix
10408 -  submat - the submatrix
10409 
10410    Level: intermediate
10411 
10412 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10413 @*/
10414 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10415 {
10416   PetscFunctionBegin;
10417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10418   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10419   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10420   PetscCheckSameComm(isrow, 2, iscol, 3);
10421   PetscValidPointer(submat, 4);
10422   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10423 
10424   if (mat->ops->restorelocalsubmatrix) {
10425     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10426   } else {
10427     PetscCall(MatDestroy(submat));
10428   }
10429   *submat = NULL;
10430   PetscFunctionReturn(PETSC_SUCCESS);
10431 }
10432 
10433 /*@
10434    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10435 
10436    Collective
10437 
10438    Input Parameter:
10439 .  mat - the matrix
10440 
10441    Output Parameter:
10442 .  is - if any rows have zero diagonals this contains the list of them
10443 
10444    Level: developer
10445 
10446 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10447 @*/
10448 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10449 {
10450   PetscFunctionBegin;
10451   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10452   PetscValidType(mat, 1);
10453   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10454   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10455 
10456   if (!mat->ops->findzerodiagonals) {
10457     Vec                diag;
10458     const PetscScalar *a;
10459     PetscInt          *rows;
10460     PetscInt           rStart, rEnd, r, nrow = 0;
10461 
10462     PetscCall(MatCreateVecs(mat, &diag, NULL));
10463     PetscCall(MatGetDiagonal(mat, diag));
10464     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10465     PetscCall(VecGetArrayRead(diag, &a));
10466     for (r = 0; r < rEnd - rStart; ++r)
10467       if (a[r] == 0.0) ++nrow;
10468     PetscCall(PetscMalloc1(nrow, &rows));
10469     nrow = 0;
10470     for (r = 0; r < rEnd - rStart; ++r)
10471       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10472     PetscCall(VecRestoreArrayRead(diag, &a));
10473     PetscCall(VecDestroy(&diag));
10474     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10475   } else {
10476     PetscUseTypeMethod(mat, findzerodiagonals, is);
10477   }
10478   PetscFunctionReturn(PETSC_SUCCESS);
10479 }
10480 
10481 /*@
10482    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10483 
10484    Collective
10485 
10486    Input Parameter:
10487 .  mat - the matrix
10488 
10489    Output Parameter:
10490 .  is - contains the list of rows with off block diagonal entries
10491 
10492    Level: developer
10493 
10494 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10495 @*/
10496 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10497 {
10498   PetscFunctionBegin;
10499   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10500   PetscValidType(mat, 1);
10501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10503 
10504   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10505   PetscFunctionReturn(PETSC_SUCCESS);
10506 }
10507 
10508 /*@C
10509   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10510 
10511   Collective; No Fortran Support
10512 
10513   Input Parameter:
10514 . mat - the matrix
10515 
10516   Output Parameter:
10517 . values - the block inverses in column major order (FORTRAN-like)
10518 
10519   Level: advanced
10520 
10521    Notes:
10522    The size of the blocks is determined by the block size of the matrix.
10523 
10524    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10525 
10526    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10527 
10528 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10529 @*/
10530 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10531 {
10532   PetscFunctionBegin;
10533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10534   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10535   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10536   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10537   PetscFunctionReturn(PETSC_SUCCESS);
10538 }
10539 
10540 /*@C
10541   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10542 
10543   Collective; No Fortran Support
10544 
10545   Input Parameters:
10546 + mat - the matrix
10547 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10548 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10549 
10550   Output Parameter:
10551 . values - the block inverses in column major order (FORTRAN-like)
10552 
10553   Level: advanced
10554 
10555   Notes:
10556   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10557 
10558   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10559 
10560 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10561 @*/
10562 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10563 {
10564   PetscFunctionBegin;
10565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10568   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10569   PetscFunctionReturn(PETSC_SUCCESS);
10570 }
10571 
10572 /*@
10573   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10574 
10575   Collective
10576 
10577   Input Parameters:
10578 + A - the matrix
10579 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10580 
10581   Level: advanced
10582 
10583   Note:
10584   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10585 
10586 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10587 @*/
10588 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10589 {
10590   const PetscScalar *vals;
10591   PetscInt          *dnnz;
10592   PetscInt           m, rstart, rend, bs, i, j;
10593 
10594   PetscFunctionBegin;
10595   PetscCall(MatInvertBlockDiagonal(A, &vals));
10596   PetscCall(MatGetBlockSize(A, &bs));
10597   PetscCall(MatGetLocalSize(A, &m, NULL));
10598   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10599   PetscCall(PetscMalloc1(m / bs, &dnnz));
10600   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10601   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10602   PetscCall(PetscFree(dnnz));
10603   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10604   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10605   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10606   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10607   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10608   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10609   PetscFunctionReturn(PETSC_SUCCESS);
10610 }
10611 
10612 /*@C
10613     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10614     via `MatTransposeColoringCreate()`.
10615 
10616     Collective
10617 
10618     Input Parameter:
10619 .   c - coloring context
10620 
10621     Level: intermediate
10622 
10623 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10624 @*/
10625 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10626 {
10627   MatTransposeColoring matcolor = *c;
10628 
10629   PetscFunctionBegin;
10630   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10631   if (--((PetscObject)matcolor)->refct > 0) {
10632     matcolor = NULL;
10633     PetscFunctionReturn(PETSC_SUCCESS);
10634   }
10635 
10636   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10637   PetscCall(PetscFree(matcolor->rows));
10638   PetscCall(PetscFree(matcolor->den2sp));
10639   PetscCall(PetscFree(matcolor->colorforcol));
10640   PetscCall(PetscFree(matcolor->columns));
10641   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10642   PetscCall(PetscHeaderDestroy(c));
10643   PetscFunctionReturn(PETSC_SUCCESS);
10644 }
10645 
10646 /*@C
10647     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10648     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10649     `MatTransposeColoring` to sparse B.
10650 
10651     Collective
10652 
10653     Input Parameters:
10654 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10655 -   B - sparse matrix
10656 
10657     Output Parameter:
10658 .   Btdense - dense matrix B^T
10659 
10660     Level: developer
10661 
10662     Note:
10663     These are used internally for some implementations of `MatRARt()`
10664 
10665 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10666 @*/
10667 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10668 {
10669   PetscFunctionBegin;
10670   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10671   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10672   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10673 
10674   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10675   PetscFunctionReturn(PETSC_SUCCESS);
10676 }
10677 
10678 /*@C
10679     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10680     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10681     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10682     `Csp` from `Cden`.
10683 
10684     Collective
10685 
10686     Input Parameters:
10687 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10688 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10689 
10690     Output Parameter:
10691 .   Csp - sparse matrix
10692 
10693     Level: developer
10694 
10695     Note:
10696     These are used internally for some implementations of `MatRARt()`
10697 
10698 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10699 @*/
10700 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10701 {
10702   PetscFunctionBegin;
10703   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10704   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10705   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10706 
10707   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10708   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10709   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10710   PetscFunctionReturn(PETSC_SUCCESS);
10711 }
10712 
10713 /*@C
10714    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10715 
10716    Collective
10717 
10718    Input Parameters:
10719 +  mat - the matrix product C
10720 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10721 
10722     Output Parameter:
10723 .   color - the new coloring context
10724 
10725     Level: intermediate
10726 
10727 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10728           `MatTransColoringApplyDenToSp()`
10729 @*/
10730 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10731 {
10732   MatTransposeColoring c;
10733   MPI_Comm             comm;
10734 
10735   PetscFunctionBegin;
10736   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10737   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10738   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10739 
10740   c->ctype = iscoloring->ctype;
10741   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10742 
10743   *color = c;
10744   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10745   PetscFunctionReturn(PETSC_SUCCESS);
10746 }
10747 
10748 /*@
10749       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10750         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10751         same, otherwise it will be larger
10752 
10753      Not Collective
10754 
10755   Input Parameter:
10756 .    A  - the matrix
10757 
10758   Output Parameter:
10759 .    state - the current state
10760 
10761   Level: intermediate
10762 
10763   Notes:
10764     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10765          different matrices
10766 
10767     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10768 
10769     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10770 
10771 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10772 @*/
10773 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10774 {
10775   PetscFunctionBegin;
10776   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10777   *state = mat->nonzerostate;
10778   PetscFunctionReturn(PETSC_SUCCESS);
10779 }
10780 
10781 /*@
10782       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10783                  matrices from each processor
10784 
10785     Collective
10786 
10787    Input Parameters:
10788 +    comm - the communicators the parallel matrix will live on
10789 .    seqmat - the input sequential matrices
10790 .    n - number of local columns (or `PETSC_DECIDE`)
10791 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10792 
10793    Output Parameter:
10794 .    mpimat - the parallel matrix generated
10795 
10796     Level: developer
10797 
10798    Note:
10799     The number of columns of the matrix in EACH processor MUST be the same.
10800 
10801 .seealso: [](chapter_matrices), `Mat`
10802 @*/
10803 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10804 {
10805   PetscMPIInt size;
10806 
10807   PetscFunctionBegin;
10808   PetscCallMPI(MPI_Comm_size(comm, &size));
10809   if (size == 1) {
10810     if (reuse == MAT_INITIAL_MATRIX) {
10811       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10812     } else {
10813       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10814     }
10815     PetscFunctionReturn(PETSC_SUCCESS);
10816   }
10817 
10818   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");
10819 
10820   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10821   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10822   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10823   PetscFunctionReturn(PETSC_SUCCESS);
10824 }
10825 
10826 /*@
10827      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10828 
10829     Collective
10830 
10831    Input Parameters:
10832 +    A   - the matrix to create subdomains from
10833 -    N   - requested number of subdomains
10834 
10835    Output Parameters:
10836 +    n   - number of subdomains resulting on this rank
10837 -    iss - `IS` list with indices of subdomains on this rank
10838 
10839     Level: advanced
10840 
10841     Note:
10842     The number of subdomains must be smaller than the communicator size
10843 
10844 .seealso: [](chapter_matrices), `Mat`, `IS`
10845 @*/
10846 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10847 {
10848   MPI_Comm    comm, subcomm;
10849   PetscMPIInt size, rank, color;
10850   PetscInt    rstart, rend, k;
10851 
10852   PetscFunctionBegin;
10853   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10854   PetscCallMPI(MPI_Comm_size(comm, &size));
10855   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10856   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);
10857   *n    = 1;
10858   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10859   color = rank / k;
10860   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10861   PetscCall(PetscMalloc1(1, iss));
10862   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10863   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10864   PetscCallMPI(MPI_Comm_free(&subcomm));
10865   PetscFunctionReturn(PETSC_SUCCESS);
10866 }
10867 
10868 /*@
10869    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10870 
10871    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10872    If they are not the same, uses `MatMatMatMult()`.
10873 
10874    Once the coarse grid problem is constructed, correct for interpolation operators
10875    that are not of full rank, which can legitimately happen in the case of non-nested
10876    geometric multigrid.
10877 
10878    Input Parameters:
10879 +  restrct - restriction operator
10880 .  dA - fine grid matrix
10881 .  interpolate - interpolation operator
10882 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10883 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10884 
10885    Output Parameter:
10886 .  A - the Galerkin coarse matrix
10887 
10888    Options Database Key:
10889 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10890 
10891    Level: developer
10892 
10893 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10894 @*/
10895 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10896 {
10897   IS  zerorows;
10898   Vec diag;
10899 
10900   PetscFunctionBegin;
10901   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10902   /* Construct the coarse grid matrix */
10903   if (interpolate == restrct) {
10904     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10905   } else {
10906     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10907   }
10908 
10909   /* If the interpolation matrix is not of full rank, A will have zero rows.
10910      This can legitimately happen in the case of non-nested geometric multigrid.
10911      In that event, we set the rows of the matrix to the rows of the identity,
10912      ignoring the equations (as the RHS will also be zero). */
10913 
10914   PetscCall(MatFindZeroRows(*A, &zerorows));
10915 
10916   if (zerorows != NULL) { /* if there are any zero rows */
10917     PetscCall(MatCreateVecs(*A, &diag, NULL));
10918     PetscCall(MatGetDiagonal(*A, diag));
10919     PetscCall(VecISSet(diag, zerorows, 1.0));
10920     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10921     PetscCall(VecDestroy(&diag));
10922     PetscCall(ISDestroy(&zerorows));
10923   }
10924   PetscFunctionReturn(PETSC_SUCCESS);
10925 }
10926 
10927 /*@C
10928     MatSetOperation - Allows user to set a matrix operation for any matrix type
10929 
10930    Logically Collective
10931 
10932     Input Parameters:
10933 +   mat - the matrix
10934 .   op - the name of the operation
10935 -   f - the function that provides the operation
10936 
10937    Level: developer
10938 
10939     Usage:
10940 .vb
10941   extern PetscErrorCode usermult(Mat, Vec, Vec);
10942 
10943   PetscCall(MatCreateXXX(comm, ..., &A));
10944   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10945 .ve
10946 
10947     Notes:
10948     See the file `include/petscmat.h` for a complete list of matrix
10949     operations, which all have the form MATOP_<OPERATION>, where
10950     <OPERATION> is the name (in all capital letters) of the
10951     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10952 
10953     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10954     sequence as the usual matrix interface routines, since they
10955     are intended to be accessed via the usual matrix interface
10956     routines, e.g.,
10957 .vb
10958   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10959 .ve
10960 
10961     In particular each function MUST return `PETSC_SUCCESS` on success and
10962     nonzero on failure.
10963 
10964     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10965 
10966 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10967 @*/
10968 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10969 {
10970   PetscFunctionBegin;
10971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10972   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10973   (((void (**)(void))mat->ops)[op]) = f;
10974   PetscFunctionReturn(PETSC_SUCCESS);
10975 }
10976 
10977 /*@C
10978     MatGetOperation - Gets a matrix operation for any matrix type.
10979 
10980     Not Collective
10981 
10982     Input Parameters:
10983 +   mat - the matrix
10984 -   op - the name of the operation
10985 
10986     Output Parameter:
10987 .   f - the function that provides the operation
10988 
10989     Level: developer
10990 
10991     Usage:
10992 .vb
10993       PetscErrorCode (*usermult)(Mat, Vec, Vec);
10994       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
10995 .ve
10996 
10997     Notes:
10998     See the file include/petscmat.h for a complete list of matrix
10999     operations, which all have the form MATOP_<OPERATION>, where
11000     <OPERATION> is the name (in all capital letters) of the
11001     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11002 
11003     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11004 
11005 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11006 @*/
11007 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11008 {
11009   PetscFunctionBegin;
11010   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11011   *f = (((void (**)(void))mat->ops)[op]);
11012   PetscFunctionReturn(PETSC_SUCCESS);
11013 }
11014 
11015 /*@
11016     MatHasOperation - Determines whether the given matrix supports the particular operation.
11017 
11018    Not Collective
11019 
11020    Input Parameters:
11021 +  mat - the matrix
11022 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11023 
11024    Output Parameter:
11025 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11026 
11027    Level: advanced
11028 
11029    Note:
11030    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11031 
11032 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11033 @*/
11034 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11035 {
11036   PetscFunctionBegin;
11037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11038   PetscValidBoolPointer(has, 3);
11039   if (mat->ops->hasoperation) {
11040     PetscUseTypeMethod(mat, hasoperation, op, has);
11041   } else {
11042     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11043     else {
11044       *has = PETSC_FALSE;
11045       if (op == MATOP_CREATE_SUBMATRIX) {
11046         PetscMPIInt size;
11047 
11048         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11049         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11050       }
11051     }
11052   }
11053   PetscFunctionReturn(PETSC_SUCCESS);
11054 }
11055 
11056 /*@
11057     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11058 
11059    Collective
11060 
11061    Input Parameter:
11062 .  mat - the matrix
11063 
11064    Output Parameter:
11065 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11066 
11067    Level: beginner
11068 
11069 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11070 @*/
11071 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11072 {
11073   PetscFunctionBegin;
11074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11075   PetscValidType(mat, 1);
11076   PetscValidBoolPointer(cong, 2);
11077   if (!mat->rmap || !mat->cmap) {
11078     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11079     PetscFunctionReturn(PETSC_SUCCESS);
11080   }
11081   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11082     PetscCall(PetscLayoutSetUp(mat->rmap));
11083     PetscCall(PetscLayoutSetUp(mat->cmap));
11084     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11085     if (*cong) mat->congruentlayouts = 1;
11086     else mat->congruentlayouts = 0;
11087   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11088   PetscFunctionReturn(PETSC_SUCCESS);
11089 }
11090 
11091 PetscErrorCode MatSetInf(Mat A)
11092 {
11093   PetscFunctionBegin;
11094   PetscUseTypeMethod(A, setinf);
11095   PetscFunctionReturn(PETSC_SUCCESS);
11096 }
11097 
11098 /*@C
11099    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
11100    and possibly removes small values from the graph structure.
11101 
11102    Collective
11103 
11104    Input Parameters:
11105 +  A - the matrix
11106 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11107 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11108 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11109 
11110    Output Parameter:
11111 .  graph - the resulting graph
11112 
11113    Level: advanced
11114 
11115 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11116 @*/
11117 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11118 {
11119   PetscFunctionBegin;
11120   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11121   PetscValidType(A, 1);
11122   PetscValidLogicalCollectiveBool(A, scale, 3);
11123   PetscValidPointer(graph, 5);
11124   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11125   PetscFunctionReturn(PETSC_SUCCESS);
11126 }
11127 
11128 /*@
11129   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11130   meaning the same memory is used for the matrix, and no new memory is allocated.
11131 
11132   Collective
11133 
11134   Input Parameter:
11135 . A - the matrix
11136 
11137   Level: intermediate
11138 
11139   Developer Note:
11140   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11141   of the arrays in the data structure are unneeded.
11142 
11143 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11144 @*/
11145 PetscErrorCode MatEliminateZeros(Mat A)
11146 {
11147   PetscFunctionBegin;
11148   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11149   PetscUseTypeMethod(A, eliminatezeros);
11150   PetscFunctionReturn(PETSC_SUCCESS);
11151 }
11152