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