xref: /petsc/src/mat/interface/matrix.c (revision 27f49a208b01d2e827ab9db411a2d16003fe9262)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36 PetscLogEvent MAT_GetMultiProcBlock;
37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameters:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameters:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameters:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](chapter_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameters:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameters:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](chapter_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameters:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameters:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameters:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameters:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903    MatSetUp - Sets up the internal matrix data structures for later use.
904 
905    Collective
906 
907    Input Parameters:
908 .  A - the matrix
909 
910    Level: intermediate
911 
912    Notes:
913    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
914    setting values in the matrix.
915 
916    If a suitable preallocation routine is used, this function does not need to be called.
917 
918    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
919 
920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
921 @*/
922 PetscErrorCode MatSetUp(Mat A)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   if (!((PetscObject)A)->type_name) {
927     PetscMPIInt size;
928 
929     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
930     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
931   }
932   if (!A->preallocated) PetscTryTypeMethod(A, setup);
933   PetscCall(PetscLayoutSetUp(A->rmap));
934   PetscCall(PetscLayoutSetUp(A->cmap));
935   A->preallocated = PETSC_TRUE;
936   PetscFunctionReturn(PETSC_SUCCESS);
937 }
938 
939 #if defined(PETSC_HAVE_SAWS)
940   #include <petscviewersaws.h>
941 #endif
942 
943 /*@C
944    MatViewFromOptions - View properties of the matrix based on options set in the options database
945 
946    Collective
947 
948    Input Parameters:
949 +  A - the matrix
950 .  obj - optional additional object that provides the options prefix to use
951 -  name - command line option
952 
953   Options Database Key:
954 .  -mat_view [viewertype]:... - the viewer and its options
955 
956    Level: intermediate
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
971 @*/
972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
977   PetscFunctionReturn(PETSC_SUCCESS);
978 }
979 
980 /*@C
981    MatView - display information about a matrix in a variety ways
982 
983    Collective
984 
985    Input Parameters:
986 +  mat - the matrix
987 -  viewer - visualization context
988 
989    Options Database Keys:
990 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
991 .  -mat_view ::ascii_info_detail - Prints more detailed info
992 .  -mat_view - Prints matrix in ASCII format
993 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
994 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
995 .  -display <name> - Sets display name (default is host)
996 .  -draw_pause <sec> - Sets number of seconds to pause after display
997 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
998 .  -viewer_socket_machine <machine> -
999 .  -viewer_socket_port <port> -
1000 .  -mat_view binary - save matrix to file in binary format
1001 -  -viewer_binary_filename <name> -
1002 
1003    Level: beginner
1004 
1005   Notes:
1006   The available visualization contexts include
1007 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1008 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1009 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1010 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1011 
1012    The user can open alternative visualization contexts with
1013 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1014 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1015          specified file; corresponding input uses MatLoad()
1016 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1017          an X window display
1018 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1019          Currently only the sequential dense and AIJ
1020          matrix types support the Socket viewer.
1021 
1022    The user can call `PetscViewerPushFormat()` to specify the output
1023    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1024    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1025 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1026 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1027 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1028 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1029          format common among all matrix types
1030 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1031          format (which is in many cases the same as the default)
1032 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1033          size and structure (not the matrix entries)
1034 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1035          the matrix structure
1036 
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072 
1073   PetscCall(PetscViewerGetFormat(viewer, &format));
1074   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1075   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1076 
1077   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1080   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1081 
1082   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1083   if (isascii) {
1084     if (!mat->preallocated) {
1085       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1086       PetscFunctionReturn(PETSC_SUCCESS);
1087     }
1088     if (!mat->assembled) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1094       MatNullSpace nullsp, transnullsp;
1095 
1096       PetscCall(PetscViewerASCIIPushTab(viewer));
1097       PetscCall(MatGetSize(mat, &rows, &cols));
1098       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1099       if (rbs != 1 || cbs != 1) {
1100         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1101         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1102       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1103       if (mat->factortype) {
1104         MatSolverType solver;
1105         PetscCall(MatFactorGetSolverType(mat, &solver));
1106         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1107       }
1108       if (mat->ops->getinfo) {
1109         MatInfo info;
1110         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1112         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1113       }
1114       PetscCall(MatGetNullSpace(mat, &nullsp));
1115       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1117       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1118       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatProductView(mat, viewer));
1122       PetscCall(PetscViewerASCIIPopTab(viewer));
1123     }
1124   } else if (issaws) {
1125 #if defined(PETSC_HAVE_SAWS)
1126     PetscMPIInt rank;
1127 
1128     PetscCall(PetscObjectName((PetscObject)mat));
1129     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1130     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1131 #endif
1132   } else if (isstring) {
1133     const char *type;
1134     PetscCall(MatGetType(mat, &type));
1135     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1136     PetscTryTypeMethod(mat, view, viewer);
1137   }
1138   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1139     PetscCall(PetscViewerASCIIPushTab(viewer));
1140     PetscUseTypeMethod(mat, viewnative, viewer);
1141     PetscCall(PetscViewerASCIIPopTab(viewer));
1142   } else if (mat->ops->view) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, view, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   }
1147   if (isascii) {
1148     PetscCall(PetscViewerGetFormat(viewer, &format));
1149     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1152   PetscFunctionReturn(PETSC_SUCCESS);
1153 }
1154 
1155 #if defined(PETSC_USE_DEBUG)
1156   #include <../src/sys/totalview/tv_data_display.h>
1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1158 {
1159   TV_add_row("Local rows", "int", &mat->rmap->n);
1160   TV_add_row("Local columns", "int", &mat->cmap->n);
1161   TV_add_row("Global rows", "int", &mat->rmap->N);
1162   TV_add_row("Global columns", "int", &mat->cmap->N);
1163   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1164   return TV_format_OK;
1165 }
1166 #endif
1167 
1168 /*@C
1169    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1170    with `MatView()`.  The matrix format is determined from the options database.
1171    Generates a parallel MPI matrix if the communicator has more than one
1172    processor.  The default matrix type is `MATAIJ`.
1173 
1174    Collective
1175 
1176    Input Parameters:
1177 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1178             or some related function before a call to `MatLoad()`
1179 -  viewer - binary/HDF5 file viewer
1180 
1181    Options Database Keys:
1182    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1183    block size
1184 .    -matload_block_size <bs> - set block size
1185 
1186    Level: beginner
1187 
1188    Notes:
1189    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1190    `Mat` before calling this routine if you wish to set it from the options database.
1191 
1192    `MatLoad()` automatically loads into the options database any options
1193    given in the file filename.info where filename is the name of the file
1194    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1195    file will be ignored if you use the -viewer_binary_skip_info option.
1196 
1197    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1198    sets the default matrix type AIJ and sets the local and global sizes.
1199    If type and/or size is already set, then the same are used.
1200 
1201    In parallel, each processor can load a subset of rows (or the
1202    entire matrix).  This routine is especially useful when a large
1203    matrix is stored on disk and only part of it is desired on each
1204    processor.  For example, a parallel solver may access only some of
1205    the rows from each processor.  The algorithm used here reads
1206    relatively small blocks of data rather than reading the entire
1207    matrix and then subsetting it.
1208 
1209    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1210    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1211    or the sequence like
1212 .vb
1213     `PetscViewer` v;
1214     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1215     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1216     `PetscViewerSetFromOptions`(v);
1217     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1218     `PetscViewerFileSetName`(v,"datafile");
1219 .ve
1220    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1221 $ -viewer_type {binary,hdf5}
1222 
1223    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1224    and src/mat/tutorials/ex10.c with the second approach.
1225 
1226    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1227    is read onto rank 0 and then shipped to its destination rank, one after another.
1228    Multiple objects, both matrices and vectors, can be stored within the same file.
1229    Their PetscObject name is ignored; they are loaded in the order of their storage.
1230 
1231    Most users should not need to know the details of the binary storage
1232    format, since `MatLoad()` and `MatView()` completely hide these details.
1233    But for anyone who's interested, the standard binary matrix storage
1234    format is
1235 
1236 .vb
1237     PetscInt    MAT_FILE_CLASSID
1238     PetscInt    number of rows
1239     PetscInt    number of columns
1240     PetscInt    total number of nonzeros
1241     PetscInt    *number nonzeros in each row
1242     PetscInt    *column indices of all nonzeros (starting index is zero)
1243     PetscScalar *values of all nonzeros
1244 .ve
1245 
1246    PETSc automatically does the byte swapping for
1247 machines that store the bytes reversed. Thus if you write your own binary
1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1249 and `PetscBinaryWrite()` to see how this may be done.
1250 
1251    Notes:
1252    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1253    Each processor's chunk is loaded independently by its owning rank.
1254    Multiple objects, both matrices and vectors, can be stored within the same file.
1255    They are looked up by their PetscObject name.
1256 
1257    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1258    by default the same structure and naming of the AIJ arrays and column count
1259    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1260 $    save example.mat A b -v7.3
1261    can be directly read by this routine (see Reference 1 for details).
1262 
1263    Depending on your MATLAB version, this format might be a default,
1264    otherwise you can set it as default in Preferences.
1265 
1266    Unless -nocompression flag is used to save the file in MATLAB,
1267    PETSc must be configured with ZLIB package.
1268 
1269    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1270 
1271    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1272 
1273    Corresponding `MatView()` is not yet implemented.
1274 
1275    The loaded matrix is actually a transpose of the original one in MATLAB,
1276    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1277    With this format, matrix is automatically transposed by PETSc,
1278    unless the matrix is marked as SPD or symmetric
1279    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1280 
1281    References:
1282 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1283 
1284 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1285  @*/
1286 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1287 {
1288   PetscBool flg;
1289 
1290   PetscFunctionBegin;
1291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1292   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1293 
1294   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1295 
1296   flg = PETSC_FALSE;
1297   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1298   if (flg) {
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1300     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1301   }
1302   flg = PETSC_FALSE;
1303   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1304   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1305 
1306   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1307   PetscUseTypeMethod(mat, load, viewer);
1308   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1309   PetscFunctionReturn(PETSC_SUCCESS);
1310 }
1311 
1312 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1313 {
1314   Mat_Redundant *redund = *redundant;
1315 
1316   PetscFunctionBegin;
1317   if (redund) {
1318     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1319       PetscCall(ISDestroy(&redund->isrow));
1320       PetscCall(ISDestroy(&redund->iscol));
1321       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1322     } else {
1323       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1324       PetscCall(PetscFree(redund->sbuf_j));
1325       PetscCall(PetscFree(redund->sbuf_a));
1326       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1327         PetscCall(PetscFree(redund->rbuf_j[i]));
1328         PetscCall(PetscFree(redund->rbuf_a[i]));
1329       }
1330       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1331     }
1332 
1333     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1334     PetscCall(PetscFree(redund));
1335   }
1336   PetscFunctionReturn(PETSC_SUCCESS);
1337 }
1338 
1339 /*@C
1340    MatDestroy - Frees space taken by a matrix.
1341 
1342    Collective
1343 
1344    Input Parameter:
1345 .  A - the matrix
1346 
1347    Level: beginner
1348 
1349    Developer Note:
1350    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1351    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1352    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1353    if changes are needed here.
1354 
1355 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1356 @*/
1357 PetscErrorCode MatDestroy(Mat *A)
1358 {
1359   PetscFunctionBegin;
1360   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1361   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1362   if (--((PetscObject)(*A))->refct > 0) {
1363     *A = NULL;
1364     PetscFunctionReturn(PETSC_SUCCESS);
1365   }
1366 
1367   /* if memory was published with SAWs then destroy it */
1368   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1369   PetscTryTypeMethod((*A), destroy);
1370 
1371   PetscCall(PetscFree((*A)->factorprefix));
1372   PetscCall(PetscFree((*A)->defaultvectype));
1373   PetscCall(PetscFree((*A)->defaultrandtype));
1374   PetscCall(PetscFree((*A)->bsizes));
1375   PetscCall(PetscFree((*A)->solvertype));
1376   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1377   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1378   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1379   PetscCall(MatProductClear(*A));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1382   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1383   PetscCall(MatDestroy(&(*A)->schur));
1384   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1385   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1386   PetscCall(PetscHeaderDestroy(A));
1387   PetscFunctionReturn(PETSC_SUCCESS);
1388 }
1389 
1390 /*@C
1391    MatSetValues - Inserts or adds a block of values into a matrix.
1392    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1393    MUST be called after all calls to `MatSetValues()` have been completed.
1394 
1395    Not Collective
1396 
1397    Input Parameters:
1398 +  mat - the matrix
1399 .  v - a logically two-dimensional array of values
1400 .  m - the number of rows
1401 .  idxm - the global indices of the rows
1402 .  n - the number of columns
1403 .  idxn - the global indices of the columns
1404 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1405 
1406    Level: beginner
1407 
1408    Notes:
1409    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1410 
1411    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1412    options cannot be mixed without intervening calls to the assembly
1413    routines.
1414 
1415    `MatSetValues()` uses 0-based row and column numbers in Fortran
1416    as well as in C.
1417 
1418    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1419    simply ignored. This allows easily inserting element stiffness matrices
1420    with homogeneous Dirchlet boundary conditions that you don't want represented
1421    in the matrix.
1422 
1423    Efficiency Alert:
1424    The routine `MatSetValuesBlocked()` may offer much better efficiency
1425    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1426 
1427    Developer Note:
1428    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1429    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1430 
1431 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1432           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1433 @*/
1434 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1435 {
1436   PetscFunctionBeginHot;
1437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1438   PetscValidType(mat, 1);
1439   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1440   PetscValidIntPointer(idxm, 3);
1441   PetscValidIntPointer(idxn, 5);
1442   MatCheckPreallocated(mat, 1);
1443 
1444   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1445   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1446 
1447   if (PetscDefined(USE_DEBUG)) {
1448     PetscInt i, j;
1449 
1450     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1451     for (i = 0; i < m; i++) {
1452       for (j = 0; j < n; j++) {
1453         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1454 #if defined(PETSC_USE_COMPLEX)
1455           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1456 #else
1457           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1458 #endif
1459       }
1460     }
1461     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1462     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1463   }
1464 
1465   if (mat->assembled) {
1466     mat->was_assembled = PETSC_TRUE;
1467     mat->assembled     = PETSC_FALSE;
1468   }
1469   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1470   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1471   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1472   PetscFunctionReturn(PETSC_SUCCESS);
1473 }
1474 
1475 /*@C
1476    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1477    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1478    MUST be called after all calls to `MatSetValues()` have been completed.
1479 
1480    Not Collective
1481 
1482    Input Parameters:
1483 +  mat - the matrix
1484 .  v - a logically two-dimensional array of values
1485 .  ism - the rows to provide
1486 .  isn - the columns to provide
1487 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1488 
1489    Level: beginner
1490 
1491    Notes:
1492    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1493 
1494    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1495    options cannot be mixed without intervening calls to the assembly
1496    routines.
1497 
1498    `MatSetValues()` uses 0-based row and column numbers in Fortran
1499    as well as in C.
1500 
1501    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1502    simply ignored. This allows easily inserting element stiffness matrices
1503    with homogeneous Dirchlet boundary conditions that you don't want represented
1504    in the matrix.
1505 
1506    Efficiency Alert:
1507    The routine `MatSetValuesBlocked()` may offer much better efficiency
1508    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1509 
1510     This is currently not optimized for any particular `ISType`
1511 
1512    Developer Notes:
1513     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1514                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1515 
1516 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1517           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1518 @*/
1519 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1520 {
1521   PetscInt        m, n;
1522   const PetscInt *rows, *cols;
1523 
1524   PetscFunctionBeginHot;
1525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1526   PetscCall(ISGetIndices(ism, &rows));
1527   PetscCall(ISGetIndices(isn, &cols));
1528   PetscCall(ISGetLocalSize(ism, &m));
1529   PetscCall(ISGetLocalSize(isn, &n));
1530   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1531   PetscCall(ISRestoreIndices(ism, &rows));
1532   PetscCall(ISRestoreIndices(isn, &cols));
1533   PetscFunctionReturn(PETSC_SUCCESS);
1534 }
1535 
1536 /*@
1537    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1538         values into a matrix
1539 
1540    Not Collective
1541 
1542    Input Parameters:
1543 +  mat - the matrix
1544 .  row - the (block) row to set
1545 -  v - a logically two-dimensional array of values
1546 
1547    Level: intermediate
1548 
1549    Notes:
1550    The values, `v`, are column-oriented (for the block version) and sorted
1551 
1552    All the nonzeros in the row must be provided
1553 
1554    The matrix must have previously had its column indices set, likely by having been assembled.
1555 
1556    The row must belong to this process
1557 
1558 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1559           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1560 @*/
1561 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1562 {
1563   PetscInt globalrow;
1564 
1565   PetscFunctionBegin;
1566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1567   PetscValidType(mat, 1);
1568   PetscValidScalarPointer(v, 3);
1569   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1570   PetscCall(MatSetValuesRow(mat, globalrow, v));
1571   PetscFunctionReturn(PETSC_SUCCESS);
1572 }
1573 
1574 /*@
1575    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1576         values into a matrix
1577 
1578    Not Collective
1579 
1580    Input Parameters:
1581 +  mat - the matrix
1582 .  row - the (block) row to set
1583 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1584 
1585    Level: advanced
1586 
1587    Notes:
1588    The values, `v`, are column-oriented for the block version.
1589 
1590    All the nonzeros in the row must be provided
1591 
1592    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1593 
1594    The row must belong to this process
1595 
1596 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1597           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1598 @*/
1599 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1600 {
1601   PetscFunctionBeginHot;
1602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1603   PetscValidType(mat, 1);
1604   MatCheckPreallocated(mat, 1);
1605   PetscValidScalarPointer(v, 3);
1606   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1607   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1608   mat->insertmode = INSERT_VALUES;
1609 
1610   if (mat->assembled) {
1611     mat->was_assembled = PETSC_TRUE;
1612     mat->assembled     = PETSC_FALSE;
1613   }
1614   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1615   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1616   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1617   PetscFunctionReturn(PETSC_SUCCESS);
1618 }
1619 
1620 /*@
1621    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1622      Using structured grid indexing
1623 
1624    Not Collective
1625 
1626    Input Parameters:
1627 +  mat - the matrix
1628 .  m - number of rows being entered
1629 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1630 .  n - number of columns being entered
1631 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1632 .  v - a logically two-dimensional array of values
1633 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1634 
1635    Level: beginner
1636 
1637    Notes:
1638    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1639 
1640    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1641    options cannot be mixed without intervening calls to the assembly
1642    routines.
1643 
1644    The grid coordinates are across the entire grid, not just the local portion
1645 
1646    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1647    as well as in C.
1648 
1649    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1650 
1651    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1652    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1653 
1654    The columns and rows in the stencil passed in MUST be contained within the
1655    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1656    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1657    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1658    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1659 
1660    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1661    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1662    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1663    `DM_BOUNDARY_PERIODIC` boundary type.
1664 
1665    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1666    a single value per point) you can skip filling those indices.
1667 
1668    Inspired by the structured grid interface to the HYPRE package
1669    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1670 
1671    Efficiency Alert:
1672    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1673    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1674 
1675    Fortran Note:
1676    `idxm` and `idxn` should be declared as
1677 $     MatStencil idxm(4,m),idxn(4,n)
1678    and the values inserted using
1679 .vb
1680     idxm(MatStencil_i,1) = i
1681     idxm(MatStencil_j,1) = j
1682     idxm(MatStencil_k,1) = k
1683     idxm(MatStencil_c,1) = c
1684     etc
1685 .ve
1686 
1687 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1688           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1689 @*/
1690 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1691 {
1692   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1693   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1694   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1695 
1696   PetscFunctionBegin;
1697   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1699   PetscValidType(mat, 1);
1700   PetscValidPointer(idxm, 3);
1701   PetscValidPointer(idxn, 5);
1702 
1703   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1704     jdxm = buf;
1705     jdxn = buf + m;
1706   } else {
1707     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1708     jdxm = bufm;
1709     jdxn = bufn;
1710   }
1711   for (i = 0; i < m; i++) {
1712     for (j = 0; j < 3 - sdim; j++) dxm++;
1713     tmp = *dxm++ - starts[0];
1714     for (j = 0; j < dim - 1; j++) {
1715       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1716       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1717     }
1718     if (mat->stencil.noc) dxm++;
1719     jdxm[i] = tmp;
1720   }
1721   for (i = 0; i < n; i++) {
1722     for (j = 0; j < 3 - sdim; j++) dxn++;
1723     tmp = *dxn++ - starts[0];
1724     for (j = 0; j < dim - 1; j++) {
1725       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1726       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1727     }
1728     if (mat->stencil.noc) dxn++;
1729     jdxn[i] = tmp;
1730   }
1731   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1732   PetscCall(PetscFree2(bufm, bufn));
1733   PetscFunctionReturn(PETSC_SUCCESS);
1734 }
1735 
1736 /*@
1737    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1738      Using structured grid indexing
1739 
1740    Not Collective
1741 
1742    Input Parameters:
1743 +  mat - the matrix
1744 .  m - number of rows being entered
1745 .  idxm - grid coordinates for matrix rows being entered
1746 .  n - number of columns being entered
1747 .  idxn - grid coordinates for matrix columns being entered
1748 .  v - a logically two-dimensional array of values
1749 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1750 
1751    Level: beginner
1752 
1753    Notes:
1754    By default the values, `v`, are row-oriented and unsorted.
1755    See `MatSetOption()` for other options.
1756 
1757    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1758    options cannot be mixed without intervening calls to the assembly
1759    routines.
1760 
1761    The grid coordinates are across the entire grid, not just the local portion
1762 
1763    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1764    as well as in C.
1765 
1766    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1767 
1768    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1769    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1770 
1771    The columns and rows in the stencil passed in MUST be contained within the
1772    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1773    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1774    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1775    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1776 
1777    Negative indices may be passed in idxm and idxn, these rows and columns are
1778    simply ignored. This allows easily inserting element stiffness matrices
1779    with homogeneous Dirchlet boundary conditions that you don't want represented
1780    in the matrix.
1781 
1782    Inspired by the structured grid interface to the HYPRE package
1783    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1784 
1785    Fortran Note:
1786    `idxm` and `idxn` should be declared as
1787 $     MatStencil idxm(4,m),idxn(4,n)
1788    and the values inserted using
1789 .vb
1790     idxm(MatStencil_i,1) = i
1791     idxm(MatStencil_j,1) = j
1792     idxm(MatStencil_k,1) = k
1793    etc
1794 .ve
1795 
1796 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1798           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1799 @*/
1800 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1801 {
1802   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1803   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1804   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1805 
1806   PetscFunctionBegin;
1807   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1809   PetscValidType(mat, 1);
1810   PetscValidPointer(idxm, 3);
1811   PetscValidPointer(idxn, 5);
1812   PetscValidScalarPointer(v, 6);
1813 
1814   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1815     jdxm = buf;
1816     jdxn = buf + m;
1817   } else {
1818     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1819     jdxm = bufm;
1820     jdxn = bufn;
1821   }
1822   for (i = 0; i < m; i++) {
1823     for (j = 0; j < 3 - sdim; j++) dxm++;
1824     tmp = *dxm++ - starts[0];
1825     for (j = 0; j < sdim - 1; j++) {
1826       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1827       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1828     }
1829     dxm++;
1830     jdxm[i] = tmp;
1831   }
1832   for (i = 0; i < n; i++) {
1833     for (j = 0; j < 3 - sdim; j++) dxn++;
1834     tmp = *dxn++ - starts[0];
1835     for (j = 0; j < sdim - 1; j++) {
1836       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1837       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1838     }
1839     dxn++;
1840     jdxn[i] = tmp;
1841   }
1842   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1843   PetscCall(PetscFree2(bufm, bufn));
1844   PetscFunctionReturn(PETSC_SUCCESS);
1845 }
1846 
1847 /*@
1848    MatSetStencil - Sets the grid information for setting values into a matrix via
1849         `MatSetValuesStencil()`
1850 
1851    Not Collective
1852 
1853    Input Parameters:
1854 +  mat - the matrix
1855 .  dim - dimension of the grid 1, 2, or 3
1856 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1857 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1858 -  dof - number of degrees of freedom per node
1859 
1860    Level: beginner
1861 
1862    Notes:
1863    Inspired by the structured grid interface to the HYPRE package
1864    (www.llnl.gov/CASC/hyper)
1865 
1866    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1867    user.
1868 
1869 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1870           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1871 @*/
1872 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1873 {
1874   PetscFunctionBegin;
1875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1876   PetscValidIntPointer(dims, 3);
1877   PetscValidIntPointer(starts, 4);
1878 
1879   mat->stencil.dim = dim + (dof > 1);
1880   for (PetscInt i = 0; i < dim; i++) {
1881     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1882     mat->stencil.starts[i] = starts[dim - i - 1];
1883   }
1884   mat->stencil.dims[dim]   = dof;
1885   mat->stencil.starts[dim] = 0;
1886   mat->stencil.noc         = (PetscBool)(dof == 1);
1887   PetscFunctionReturn(PETSC_SUCCESS);
1888 }
1889 
1890 /*@C
1891    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1892 
1893    Not Collective
1894 
1895    Input Parameters:
1896 +  mat - the matrix
1897 .  v - a logically two-dimensional array of values
1898 .  m  - the number of block rows
1899 .  idxm - the global block indices
1900 .  n - the number of block columns
1901 .  idxn - the global block indices
1902 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1903 
1904    Level: intermediate
1905 
1906    Notes:
1907    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1908    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1909 
1910    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1911    NOT the total number of rows/columns; for example, if the block size is 2 and
1912    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1913    The values in idxm would be 1 2; that is the first index for each block divided by
1914    the block size.
1915 
1916    You must call `MatSetBlockSize()` when constructing this matrix (before
1917    preallocating it).
1918 
1919    By default the values, `v`, are row-oriented, so the layout of
1920    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1921 
1922    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1923    options cannot be mixed without intervening calls to the assembly
1924    routines.
1925 
1926    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1927    as well as in C.
1928 
1929    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1930    simply ignored. This allows easily inserting element stiffness matrices
1931    with homogeneous Dirchlet boundary conditions that you don't want represented
1932    in the matrix.
1933 
1934    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1935    internal searching must be done to determine where to place the
1936    data in the matrix storage space.  By instead inserting blocks of
1937    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1938    reduced.
1939 
1940    Example:
1941 .vb
1942    Suppose m=n=2 and block size(bs) = 2 The array is
1943 
1944    1  2  | 3  4
1945    5  6  | 7  8
1946    - - - | - - -
1947    9  10 | 11 12
1948    13 14 | 15 16
1949 
1950    v[] should be passed in like
1951    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1952 
1953   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1954    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1955 .ve
1956 
1957 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1958 @*/
1959 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1960 {
1961   PetscFunctionBeginHot;
1962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1963   PetscValidType(mat, 1);
1964   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1965   PetscValidIntPointer(idxm, 3);
1966   PetscValidIntPointer(idxn, 5);
1967   MatCheckPreallocated(mat, 1);
1968   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1969   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1970   if (PetscDefined(USE_DEBUG)) {
1971     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1972     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1973   }
1974   if (PetscDefined(USE_DEBUG)) {
1975     PetscInt rbs, cbs, M, N, i;
1976     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1977     PetscCall(MatGetSize(mat, &M, &N));
1978     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1979     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1980   }
1981   if (mat->assembled) {
1982     mat->was_assembled = PETSC_TRUE;
1983     mat->assembled     = PETSC_FALSE;
1984   }
1985   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1986   if (mat->ops->setvaluesblocked) {
1987     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1988   } else {
1989     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1990     PetscInt i, j, bs, cbs;
1991 
1992     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1993     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1994       iidxm = buf;
1995       iidxn = buf + m * bs;
1996     } else {
1997       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1998       iidxm = bufr;
1999       iidxn = bufc;
2000     }
2001     for (i = 0; i < m; i++) {
2002       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2003     }
2004     if (m != n || bs != cbs || idxm != idxn) {
2005       for (i = 0; i < n; i++) {
2006         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2007       }
2008     } else iidxn = iidxm;
2009     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2010     PetscCall(PetscFree2(bufr, bufc));
2011   }
2012   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2013   PetscFunctionReturn(PETSC_SUCCESS);
2014 }
2015 
2016 /*@C
2017    MatGetValues - Gets a block of local values from a matrix.
2018 
2019    Not Collective; can only return values that are owned by the give process
2020 
2021    Input Parameters:
2022 +  mat - the matrix
2023 .  v - a logically two-dimensional array for storing the values
2024 .  m  - the number of rows
2025 .  idxm - the  global indices of the rows
2026 .  n - the number of columns
2027 -  idxn - the global indices of the columns
2028 
2029    Level: advanced
2030 
2031    Notes:
2032      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2033      The values, `v`, are then returned in a row-oriented format,
2034      analogous to that used by default in `MatSetValues()`.
2035 
2036      `MatGetValues()` uses 0-based row and column numbers in
2037      Fortran as well as in C.
2038 
2039      `MatGetValues()` requires that the matrix has been assembled
2040      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2041      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2042      without intermediate matrix assembly.
2043 
2044      Negative row or column indices will be ignored and those locations in `v` will be
2045      left unchanged.
2046 
2047      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2048      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2049      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2050 
2051 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2052 @*/
2053 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2054 {
2055   PetscFunctionBegin;
2056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2057   PetscValidType(mat, 1);
2058   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2059   PetscValidIntPointer(idxm, 3);
2060   PetscValidIntPointer(idxn, 5);
2061   PetscValidScalarPointer(v, 6);
2062   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2063   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2064   MatCheckPreallocated(mat, 1);
2065 
2066   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2067   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2068   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2069   PetscFunctionReturn(PETSC_SUCCESS);
2070 }
2071 
2072 /*@C
2073    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2074      defined previously by `MatSetLocalToGlobalMapping()`
2075 
2076    Not Collective
2077 
2078    Input Parameters:
2079 +  mat - the matrix
2080 .  nrow - number of rows
2081 .  irow - the row local indices
2082 .  ncol - number of columns
2083 -  icol - the column local indices
2084 
2085    Output Parameter:
2086 .  y -  a logically two-dimensional array of values
2087 
2088    Level: advanced
2089 
2090    Notes:
2091      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2092 
2093      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2094      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2095      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2096      with `MatSetLocalToGlobalMapping()`.
2097 
2098    Developer Note:
2099       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2100       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2101 
2102 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2103           `MatSetValuesLocal()`, `MatGetValues()`
2104 @*/
2105 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2106 {
2107   PetscFunctionBeginHot;
2108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2109   PetscValidType(mat, 1);
2110   MatCheckPreallocated(mat, 1);
2111   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2112   PetscValidIntPointer(irow, 3);
2113   PetscValidIntPointer(icol, 5);
2114   if (PetscDefined(USE_DEBUG)) {
2115     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2116     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2117   }
2118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2119   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2120   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2121   else {
2122     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2123     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2124       irowm = buf;
2125       icolm = buf + nrow;
2126     } else {
2127       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2128       irowm = bufr;
2129       icolm = bufc;
2130     }
2131     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2133     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2134     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2135     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2136     PetscCall(PetscFree2(bufr, bufc));
2137   }
2138   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2139   PetscFunctionReturn(PETSC_SUCCESS);
2140 }
2141 
2142 /*@
2143   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2144   the same size. Currently, this can only be called once and creates the given matrix.
2145 
2146   Not Collective
2147 
2148   Input Parameters:
2149 + mat - the matrix
2150 . nb - the number of blocks
2151 . bs - the number of rows (and columns) in each block
2152 . rows - a concatenation of the rows for each block
2153 - v - a concatenation of logically two-dimensional arrays of values
2154 
2155   Level: advanced
2156 
2157   Note:
2158   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2159 
2160   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2161 
2162 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2163           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2164 @*/
2165 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2166 {
2167   PetscFunctionBegin;
2168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2169   PetscValidType(mat, 1);
2170   PetscValidIntPointer(rows, 4);
2171   PetscValidScalarPointer(v, 5);
2172   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2173 
2174   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2175   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2176   else {
2177     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2178   }
2179   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@
2184    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2185    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2186    using a local (per-processor) numbering.
2187 
2188    Not Collective
2189 
2190    Input Parameters:
2191 +  x - the matrix
2192 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2193 -  cmapping - column mapping
2194 
2195    Level: intermediate
2196 
2197    Note:
2198    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2199 
2200 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2201 @*/
2202 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2203 {
2204   PetscFunctionBegin;
2205   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2206   PetscValidType(x, 1);
2207   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2208   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2209   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2210   else {
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2212     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2213   }
2214   PetscFunctionReturn(PETSC_SUCCESS);
2215 }
2216 
2217 /*@
2218    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2219 
2220    Not Collective
2221 
2222    Input Parameter:
2223 .  A - the matrix
2224 
2225    Output Parameters:
2226 + rmapping - row mapping
2227 - cmapping - column mapping
2228 
2229    Level: advanced
2230 
2231 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2232 @*/
2233 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2234 {
2235   PetscFunctionBegin;
2236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2237   PetscValidType(A, 1);
2238   if (rmapping) {
2239     PetscValidPointer(rmapping, 2);
2240     *rmapping = A->rmap->mapping;
2241   }
2242   if (cmapping) {
2243     PetscValidPointer(cmapping, 3);
2244     *cmapping = A->cmap->mapping;
2245   }
2246   PetscFunctionReturn(PETSC_SUCCESS);
2247 }
2248 
2249 /*@
2250    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2251 
2252    Logically Collective
2253 
2254    Input Parameters:
2255 +  A - the matrix
2256 . rmap - row layout
2257 - cmap - column layout
2258 
2259    Level: advanced
2260 
2261    Note:
2262    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2263 
2264 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2265 @*/
2266 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2267 {
2268   PetscFunctionBegin;
2269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2270   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2271   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2272   PetscFunctionReturn(PETSC_SUCCESS);
2273 }
2274 
2275 /*@
2276    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2277 
2278    Not Collective
2279 
2280    Input Parameter:
2281 .  A - the matrix
2282 
2283    Output Parameters:
2284 + rmap - row layout
2285 - cmap - column layout
2286 
2287    Level: advanced
2288 
2289 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2290 @*/
2291 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2292 {
2293   PetscFunctionBegin;
2294   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2295   PetscValidType(A, 1);
2296   if (rmap) {
2297     PetscValidPointer(rmap, 2);
2298     *rmap = A->rmap;
2299   }
2300   if (cmap) {
2301     PetscValidPointer(cmap, 3);
2302     *cmap = A->cmap;
2303   }
2304   PetscFunctionReturn(PETSC_SUCCESS);
2305 }
2306 
2307 /*@C
2308    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2309    using a local numbering of the nodes.
2310 
2311    Not Collective
2312 
2313    Input Parameters:
2314 +  mat - the matrix
2315 .  nrow - number of rows
2316 .  irow - the row local indices
2317 .  ncol - number of columns
2318 .  icol - the column local indices
2319 .  y -  a logically two-dimensional array of values
2320 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2321 
2322    Level: intermediate
2323 
2324    Notes:
2325    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2326       `MatSetUp()` before using this routine
2327 
2328    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2329 
2330    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2331    options cannot be mixed without intervening calls to the assembly
2332    routines.
2333 
2334    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2335    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2336 
2337    Developer Note:
2338     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2339                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2340 
2341 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2342           `MatGetValuesLocal()`
2343 @*/
2344 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2345 {
2346   PetscFunctionBeginHot;
2347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2348   PetscValidType(mat, 1);
2349   MatCheckPreallocated(mat, 1);
2350   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2351   PetscValidIntPointer(irow, 3);
2352   PetscValidIntPointer(icol, 5);
2353   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2354   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2355   if (PetscDefined(USE_DEBUG)) {
2356     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2357     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2358   }
2359 
2360   if (mat->assembled) {
2361     mat->was_assembled = PETSC_TRUE;
2362     mat->assembled     = PETSC_FALSE;
2363   }
2364   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2365   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2366   else {
2367     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2368     const PetscInt *irowm, *icolm;
2369 
2370     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2371       bufr  = buf;
2372       bufc  = buf + nrow;
2373       irowm = bufr;
2374       icolm = bufc;
2375     } else {
2376       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2377       irowm = bufr;
2378       icolm = bufc;
2379     }
2380     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2381     else irowm = irow;
2382     if (mat->cmap->mapping) {
2383       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2384         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2385       } else icolm = irowm;
2386     } else icolm = icol;
2387     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2388     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2389   }
2390   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2391   PetscFunctionReturn(PETSC_SUCCESS);
2392 }
2393 
2394 /*@C
2395    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2396    using a local ordering of the nodes a block at a time.
2397 
2398    Not Collective
2399 
2400    Input Parameters:
2401 +  x - the matrix
2402 .  nrow - number of rows
2403 .  irow - the row local indices
2404 .  ncol - number of columns
2405 .  icol - the column local indices
2406 .  y -  a logically two-dimensional array of values
2407 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2408 
2409    Level: intermediate
2410 
2411    Notes:
2412    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2413       `MatSetUp()` before using this routine
2414 
2415    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2416       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2417 
2418    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2419    options cannot be mixed without intervening calls to the assembly
2420    routines.
2421 
2422    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2423    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2424 
2425    Developer Note:
2426     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2427                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2428 
2429 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2430           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2431 @*/
2432 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2433 {
2434   PetscFunctionBeginHot;
2435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2436   PetscValidType(mat, 1);
2437   MatCheckPreallocated(mat, 1);
2438   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2439   PetscValidIntPointer(irow, 3);
2440   PetscValidIntPointer(icol, 5);
2441   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2442   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2443   if (PetscDefined(USE_DEBUG)) {
2444     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2445     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2446   }
2447 
2448   if (mat->assembled) {
2449     mat->was_assembled = PETSC_TRUE;
2450     mat->assembled     = PETSC_FALSE;
2451   }
2452   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2453     PetscInt irbs, rbs;
2454     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2455     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2456     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2457   }
2458   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2459     PetscInt icbs, cbs;
2460     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2461     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2462     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2463   }
2464   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2465   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2466   else {
2467     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2468     const PetscInt *irowm, *icolm;
2469 
2470     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2471       bufr  = buf;
2472       bufc  = buf + nrow;
2473       irowm = bufr;
2474       icolm = bufc;
2475     } else {
2476       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2477       irowm = bufr;
2478       icolm = bufc;
2479     }
2480     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2481     else irowm = irow;
2482     if (mat->cmap->mapping) {
2483       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2484         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2485       } else icolm = irowm;
2486     } else icolm = icol;
2487     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2488     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2489   }
2490   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2491   PetscFunctionReturn(PETSC_SUCCESS);
2492 }
2493 
2494 /*@
2495    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2496 
2497    Collective
2498 
2499    Input Parameters:
2500 +  mat - the matrix
2501 -  x   - the vector to be multiplied
2502 
2503    Output Parameter:
2504 .  y - the result
2505 
2506    Level: developer
2507 
2508    Note:
2509    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2510    call `MatMultDiagonalBlock`(A,y,y).
2511 
2512 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2513 @*/
2514 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2515 {
2516   PetscFunctionBegin;
2517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2518   PetscValidType(mat, 1);
2519   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2520   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2521 
2522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2524   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2525   MatCheckPreallocated(mat, 1);
2526 
2527   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2528   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2529   PetscFunctionReturn(PETSC_SUCCESS);
2530 }
2531 
2532 /*@
2533    MatMult - Computes the matrix-vector product, y = Ax.
2534 
2535    Neighbor-wise Collective
2536 
2537    Input Parameters:
2538 +  mat - the matrix
2539 -  x   - the vector to be multiplied
2540 
2541    Output Parameter:
2542 .  y - the result
2543 
2544    Level: beginner
2545 
2546    Note:
2547    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2548    call `MatMult`(A,y,y).
2549 
2550 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2551 @*/
2552 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2553 {
2554   PetscFunctionBegin;
2555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2556   PetscValidType(mat, 1);
2557   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2558   VecCheckAssembled(x);
2559   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2560   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2561   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2562   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2563   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2564   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2565   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2566   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2567   PetscCall(VecSetErrorIfLocked(y, 3));
2568   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2569   MatCheckPreallocated(mat, 1);
2570 
2571   PetscCall(VecLockReadPush(x));
2572   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2573   PetscUseTypeMethod(mat, mult, x, y);
2574   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2575   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2576   PetscCall(VecLockReadPop(x));
2577   PetscFunctionReturn(PETSC_SUCCESS);
2578 }
2579 
2580 /*@
2581    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2582 
2583    Neighbor-wise Collective
2584 
2585    Input Parameters:
2586 +  mat - the matrix
2587 -  x   - the vector to be multiplied
2588 
2589    Output Parameter:
2590 .  y - the result
2591 
2592    Level: beginner
2593 
2594    Notes:
2595    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2596    call `MatMultTranspose`(A,y,y).
2597 
2598    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2599    use `MatMultHermitianTranspose()`
2600 
2601 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2602 @*/
2603 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2604 {
2605   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2606 
2607   PetscFunctionBegin;
2608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2609   PetscValidType(mat, 1);
2610   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2611   VecCheckAssembled(x);
2612   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2613 
2614   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2615   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2616   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2617   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2618   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2619   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2620   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2621   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2622   MatCheckPreallocated(mat, 1);
2623 
2624   if (!mat->ops->multtranspose) {
2625     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2626     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2627   } else op = mat->ops->multtranspose;
2628   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2629   PetscCall(VecLockReadPush(x));
2630   PetscCall((*op)(mat, x, y));
2631   PetscCall(VecLockReadPop(x));
2632   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2633   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2634   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2635   PetscFunctionReturn(PETSC_SUCCESS);
2636 }
2637 
2638 /*@
2639    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2640 
2641    Neighbor-wise Collective
2642 
2643    Input Parameters:
2644 +  mat - the matrix
2645 -  x   - the vector to be multilplied
2646 
2647    Output Parameter:
2648 .  y - the result
2649 
2650    Level: beginner
2651 
2652    Notes:
2653    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2654    call `MatMultHermitianTranspose`(A,y,y).
2655 
2656    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2657 
2658    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2659 
2660 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2661 @*/
2662 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2663 {
2664   PetscFunctionBegin;
2665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2666   PetscValidType(mat, 1);
2667   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2668   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2669 
2670   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2671   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2672   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2673   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2674   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2675   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2676   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2677   MatCheckPreallocated(mat, 1);
2678 
2679   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2680 #if defined(PETSC_USE_COMPLEX)
2681   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2682     PetscCall(VecLockReadPush(x));
2683     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2684     else PetscUseTypeMethod(mat, mult, x, y);
2685     PetscCall(VecLockReadPop(x));
2686   } else {
2687     Vec w;
2688     PetscCall(VecDuplicate(x, &w));
2689     PetscCall(VecCopy(x, w));
2690     PetscCall(VecConjugate(w));
2691     PetscCall(MatMultTranspose(mat, w, y));
2692     PetscCall(VecDestroy(&w));
2693     PetscCall(VecConjugate(y));
2694   }
2695   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2696 #else
2697   PetscCall(MatMultTranspose(mat, x, y));
2698 #endif
2699   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2700   PetscFunctionReturn(PETSC_SUCCESS);
2701 }
2702 
2703 /*@
2704     MatMultAdd -  Computes v3 = v2 + A * v1.
2705 
2706     Neighbor-wise Collective
2707 
2708     Input Parameters:
2709 +   mat - the matrix
2710 .   v1 - the vector to be multiplied by `mat`
2711 -   v2 - the vector to be added to the result
2712 
2713     Output Parameter:
2714 .   v3 - the result
2715 
2716     Level: beginner
2717 
2718     Note:
2719     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2720     call `MatMultAdd`(A,v1,v2,v1).
2721 
2722 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2723 @*/
2724 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2725 {
2726   PetscFunctionBegin;
2727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2728   PetscValidType(mat, 1);
2729   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2730   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2731   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2732 
2733   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2735   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2736   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2737      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2738   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2739   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2740   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2741   MatCheckPreallocated(mat, 1);
2742 
2743   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2744   PetscCall(VecLockReadPush(v1));
2745   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2746   PetscCall(VecLockReadPop(v1));
2747   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2748   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2749   PetscFunctionReturn(PETSC_SUCCESS);
2750 }
2751 
2752 /*@
2753    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2754 
2755    Neighbor-wise Collective
2756 
2757    Input Parameters:
2758 +  mat - the matrix
2759 .  v1 - the vector to be multipled by the transpose of the matrix
2760 -  v2 - the vector to be added to the result
2761 
2762    Output Parameter:
2763 .  v3 - the result
2764 
2765    Level: beginner
2766 
2767    Note:
2768    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2769    call `MatMultTransposeAdd`(A,v1,v2,v1).
2770 
2771 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2772 @*/
2773 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2774 {
2775   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2776 
2777   PetscFunctionBegin;
2778   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2779   PetscValidType(mat, 1);
2780   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2781   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2782   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2783 
2784   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2785   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2786   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2787   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2788   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2789   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2790   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2791   MatCheckPreallocated(mat, 1);
2792 
2793   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2794   PetscCall(VecLockReadPush(v1));
2795   PetscCall((*op)(mat, v1, v2, v3));
2796   PetscCall(VecLockReadPop(v1));
2797   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2798   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2799   PetscFunctionReturn(PETSC_SUCCESS);
2800 }
2801 
2802 /*@
2803    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2804 
2805    Neighbor-wise Collective
2806 
2807    Input Parameters:
2808 +  mat - the matrix
2809 .  v1 - the vector to be multiplied by the Hermitian transpose
2810 -  v2 - the vector to be added to the result
2811 
2812    Output Parameter:
2813 .  v3 - the result
2814 
2815    Level: beginner
2816 
2817    Note:
2818    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2819    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2820 
2821 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2822 @*/
2823 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2824 {
2825   PetscFunctionBegin;
2826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2827   PetscValidType(mat, 1);
2828   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2829   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2830   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2831 
2832   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2833   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2834   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2835   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2836   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2837   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2838   MatCheckPreallocated(mat, 1);
2839 
2840   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2841   PetscCall(VecLockReadPush(v1));
2842   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2843   else {
2844     Vec w, z;
2845     PetscCall(VecDuplicate(v1, &w));
2846     PetscCall(VecCopy(v1, w));
2847     PetscCall(VecConjugate(w));
2848     PetscCall(VecDuplicate(v3, &z));
2849     PetscCall(MatMultTranspose(mat, w, z));
2850     PetscCall(VecDestroy(&w));
2851     PetscCall(VecConjugate(z));
2852     if (v2 != v3) {
2853       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2854     } else {
2855       PetscCall(VecAXPY(v3, 1.0, z));
2856     }
2857     PetscCall(VecDestroy(&z));
2858   }
2859   PetscCall(VecLockReadPop(v1));
2860   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2861   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2862   PetscFunctionReturn(PETSC_SUCCESS);
2863 }
2864 
2865 /*@C
2866    MatGetFactorType - gets the type of factorization it is
2867 
2868    Not Collective
2869 
2870    Input Parameters:
2871 .  mat - the matrix
2872 
2873    Output Parameter:
2874 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2875 
2876    Level: intermediate
2877 
2878 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2879           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2880 @*/
2881 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2882 {
2883   PetscFunctionBegin;
2884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2885   PetscValidType(mat, 1);
2886   PetscValidPointer(t, 2);
2887   *t = mat->factortype;
2888   PetscFunctionReturn(PETSC_SUCCESS);
2889 }
2890 
2891 /*@C
2892    MatSetFactorType - sets the type of factorization it is
2893 
2894    Logically Collective
2895 
2896    Input Parameters:
2897 +  mat - the matrix
2898 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2899 
2900    Level: intermediate
2901 
2902 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2903           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2904 @*/
2905 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2906 {
2907   PetscFunctionBegin;
2908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2909   PetscValidType(mat, 1);
2910   mat->factortype = t;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915    MatGetInfo - Returns information about matrix storage (number of
2916    nonzeros, memory, etc.).
2917 
2918    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2919 
2920    Input Parameters:
2921 +  mat - the matrix
2922 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2923 
2924    Output Parameter:
2925 .  info - matrix information context
2926 
2927    Notes:
2928    The `MatInfo` context contains a variety of matrix data, including
2929    number of nonzeros allocated and used, number of mallocs during
2930    matrix assembly, etc.  Additional information for factored matrices
2931    is provided (such as the fill ratio, number of mallocs during
2932    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2933    when using the runtime options
2934 $       -info -mat_view ::ascii_info
2935 
2936    Example:
2937    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2938    data within the MatInfo context.  For example,
2939 .vb
2940       MatInfo info;
2941       Mat     A;
2942       double  mal, nz_a, nz_u;
2943 
2944       MatGetInfo(A,MAT_LOCAL,&info);
2945       mal  = info.mallocs;
2946       nz_a = info.nz_allocated;
2947 .ve
2948 
2949    Fortran users should declare info as a double precision
2950    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2951    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2952    a complete list of parameter names.
2953 .vb
2954       double  precision info(MAT_INFO_SIZE)
2955       double  precision mal, nz_a
2956       Mat     A
2957       integer ierr
2958 
2959       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2960       mal = info(MAT_INFO_MALLOCS)
2961       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2962 .ve
2963 
2964     Level: intermediate
2965 
2966     Developer Note:
2967     The Fortran interface is not autogenerated as the
2968     interface definition cannot be generated correctly [due to `MatInfo` argument]
2969 
2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2971 @*/
2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2973 {
2974   PetscFunctionBegin;
2975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2976   PetscValidType(mat, 1);
2977   PetscValidPointer(info, 3);
2978   MatCheckPreallocated(mat, 1);
2979   PetscUseTypeMethod(mat, getinfo, flag, info);
2980   PetscFunctionReturn(PETSC_SUCCESS);
2981 }
2982 
2983 /*
2984    This is used by external packages where it is not easy to get the info from the actual
2985    matrix factorization.
2986 */
2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2988 {
2989   PetscFunctionBegin;
2990   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2991   PetscFunctionReturn(PETSC_SUCCESS);
2992 }
2993 
2994 /*@C
2995    MatLUFactor - Performs in-place LU factorization of matrix.
2996 
2997    Collective
2998 
2999    Input Parameters:
3000 +  mat - the matrix
3001 .  row - row permutation
3002 .  col - column permutation
3003 -  info - options for factorization, includes
3004 .vb
3005           fill - expected fill as ratio of original fill.
3006           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3007                    Run with the option -info to determine an optimal value to use
3008 .ve
3009    Level: developer
3010 
3011    Notes:
3012    Most users should employ the `KSP` interface for linear solvers
3013    instead of working directly with matrix algebra routines such as this.
3014    See, e.g., `KSPCreate()`.
3015 
3016    This changes the state of the matrix to a factored matrix; it cannot be used
3017    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3018 
3019    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3020    when not using `KSP`.
3021 
3022    Developer Note:
3023    The Fortran interface is not autogenerated as the
3024    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3025 
3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3027           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3028 @*/
3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3030 {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3037   if (info) PetscValidPointer(info, 4);
3038   PetscValidType(mat, 1);
3039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3041   MatCheckPreallocated(mat, 1);
3042   if (!info) {
3043     PetscCall(MatFactorInfoInitialize(&tinfo));
3044     info = &tinfo;
3045   }
3046 
3047   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3048   PetscUseTypeMethod(mat, lufactor, row, col, info);
3049   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055    MatILUFactor - Performs in-place ILU factorization of matrix.
3056 
3057    Collective
3058 
3059    Input Parameters:
3060 +  mat - the matrix
3061 .  row - row permutation
3062 .  col - column permutation
3063 -  info - structure containing
3064 .vb
3065       levels - number of levels of fill.
3066       expected fill - as ratio of original fill.
3067       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3068                 missing diagonal entries)
3069 .ve
3070 
3071    Level: developer
3072 
3073    Notes:
3074    Most users should employ the `KSP` interface for linear solvers
3075    instead of working directly with matrix algebra routines such as this.
3076    See, e.g., `KSPCreate()`.
3077 
3078    Probably really in-place only when level of fill is zero, otherwise allocates
3079    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3080    when not using `KSP`.
3081 
3082    Developer Note:
3083    The Fortran interface is not autogenerated as the
3084    interface definition cannot be generated correctly [due to MatFactorInfo]
3085 
3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3087 @*/
3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3089 {
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3092   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3093   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3094   PetscValidPointer(info, 4);
3095   PetscValidType(mat, 1);
3096   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3099   MatCheckPreallocated(mat, 1);
3100 
3101   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3102   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3103   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3105   PetscFunctionReturn(PETSC_SUCCESS);
3106 }
3107 
3108 /*@C
3109    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3110    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3111 
3112    Collective
3113 
3114    Input Parameters:
3115 +  fact - the factor matrix obtained with `MatGetFactor()`
3116 .  mat - the matrix
3117 .  row - the row permutation
3118 .  col - the column permutation
3119 -  info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123 .ve
3124 
3125    Level: developer
3126 
3127    Notes:
3128     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3129 
3130    Most users should employ the simplified `KSP` interface for linear solvers
3131    instead of working directly with matrix algebra routines such as this.
3132    See, e.g., `KSPCreate()`.
3133 
3134    Developer Note:
3135    The Fortran interface is not autogenerated as the
3136    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137 
3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139 @*/
3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141 {
3142   MatFactorInfo tinfo;
3143 
3144   PetscFunctionBegin;
3145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3146   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3147   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3148   if (info) PetscValidPointer(info, 5);
3149   PetscValidType(mat, 2);
3150   PetscValidPointer(fact, 1);
3151   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3153   if (!(fact)->ops->lufactorsymbolic) {
3154     MatSolverType stype;
3155     PetscCall(MatFactorGetSolverType(fact, &stype));
3156     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3157   }
3158   MatCheckPreallocated(mat, 2);
3159   if (!info) {
3160     PetscCall(MatFactorInfoInitialize(&tinfo));
3161     info = &tinfo;
3162   }
3163 
3164   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3165   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3166   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3167   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3168   PetscFunctionReturn(PETSC_SUCCESS);
3169 }
3170 
3171 /*@C
3172    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3173    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3174 
3175    Collective
3176 
3177    Input Parameters:
3178 +  fact - the factor matrix obtained with `MatGetFactor()`
3179 .  mat - the matrix
3180 -  info - options for factorization
3181 
3182    Level: developer
3183 
3184    Notes:
3185    See `MatLUFactor()` for in-place factorization.  See
3186    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3187 
3188    Most users should employ the `KSP` interface for linear solvers
3189    instead of working directly with matrix algebra routines such as this.
3190    See, e.g., `KSPCreate()`.
3191 
3192     Developer Note:
3193     The Fortran interface is not autogenerated as the
3194     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3195 
3196 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3197 @*/
3198 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3199 {
3200   MatFactorInfo tinfo;
3201 
3202   PetscFunctionBegin;
3203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3204   PetscValidType(mat, 2);
3205   PetscValidPointer(fact, 1);
3206   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3208   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,
3209              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3210 
3211   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3212   MatCheckPreallocated(mat, 2);
3213   if (!info) {
3214     PetscCall(MatFactorInfoInitialize(&tinfo));
3215     info = &tinfo;
3216   }
3217 
3218   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3219   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3220   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3221   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3222   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3223   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3224   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3225   PetscFunctionReturn(PETSC_SUCCESS);
3226 }
3227 
3228 /*@C
3229    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3230    symmetric matrix.
3231 
3232    Collective
3233 
3234    Input Parameters:
3235 +  mat - the matrix
3236 .  perm - row and column permutations
3237 -  f - expected fill as ratio of original fill
3238 
3239    Level: developer
3240 
3241    Notes:
3242    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3243    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3244 
3245    Most users should employ the `KSP` interface for linear solvers
3246    instead of working directly with matrix algebra routines such as this.
3247    See, e.g., `KSPCreate()`.
3248 
3249    Developer Note:
3250    The Fortran interface is not autogenerated as the
3251    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3252 
3253 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3254           `MatGetOrdering()`
3255 @*/
3256 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3257 {
3258   MatFactorInfo tinfo;
3259 
3260   PetscFunctionBegin;
3261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3262   PetscValidType(mat, 1);
3263   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3264   if (info) PetscValidPointer(info, 3);
3265   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3268   MatCheckPreallocated(mat, 1);
3269   if (!info) {
3270     PetscCall(MatFactorInfoInitialize(&tinfo));
3271     info = &tinfo;
3272   }
3273 
3274   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3275   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3276   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3277   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3278   PetscFunctionReturn(PETSC_SUCCESS);
3279 }
3280 
3281 /*@C
3282    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3283    of a symmetric matrix.
3284 
3285    Collective
3286 
3287    Input Parameters:
3288 +  fact - the factor matrix obtained with `MatGetFactor()`
3289 .  mat - the matrix
3290 .  perm - row and column permutations
3291 -  info - options for factorization, includes
3292 .vb
3293           fill - expected fill as ratio of original fill.
3294           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3295                    Run with the option -info to determine an optimal value to use
3296 .ve
3297 
3298    Level: developer
3299 
3300    Notes:
3301    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3302    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3303 
3304    Most users should employ the `KSP` interface for linear solvers
3305    instead of working directly with matrix algebra routines such as this.
3306    See, e.g., `KSPCreate()`.
3307 
3308    Developer Note:
3309    The Fortran interface is not autogenerated as the
3310    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3311 
3312 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3313           `MatGetOrdering()`
3314 @*/
3315 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3316 {
3317   MatFactorInfo tinfo;
3318 
3319   PetscFunctionBegin;
3320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3321   PetscValidType(mat, 2);
3322   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3323   if (info) PetscValidPointer(info, 4);
3324   PetscValidPointer(fact, 1);
3325   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3326   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3327   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3328   if (!(fact)->ops->choleskyfactorsymbolic) {
3329     MatSolverType stype;
3330     PetscCall(MatFactorGetSolverType(fact, &stype));
3331     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3332   }
3333   MatCheckPreallocated(mat, 2);
3334   if (!info) {
3335     PetscCall(MatFactorInfoInitialize(&tinfo));
3336     info = &tinfo;
3337   }
3338 
3339   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3340   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3341   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3342   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3343   PetscFunctionReturn(PETSC_SUCCESS);
3344 }
3345 
3346 /*@C
3347    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3348    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3349    `MatCholeskyFactorSymbolic()`.
3350 
3351    Collective
3352 
3353    Input Parameters:
3354 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3355 .  mat - the initial matrix that is to be factored
3356 -  info - options for factorization
3357 
3358    Level: developer
3359 
3360    Note:
3361    Most users should employ the `KSP` interface for linear solvers
3362    instead of working directly with matrix algebra routines such as this.
3363    See, e.g., `KSPCreate()`.
3364 
3365    Developer Note:
3366    The Fortran interface is not autogenerated as the
3367    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3368 
3369 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3370 @*/
3371 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3372 {
3373   MatFactorInfo tinfo;
3374 
3375   PetscFunctionBegin;
3376   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3377   PetscValidType(mat, 2);
3378   PetscValidPointer(fact, 1);
3379   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3380   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3381   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3382   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,
3383              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3384   MatCheckPreallocated(mat, 2);
3385   if (!info) {
3386     PetscCall(MatFactorInfoInitialize(&tinfo));
3387     info = &tinfo;
3388   }
3389 
3390   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3391   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3392   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3393   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3394   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3395   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3396   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3397   PetscFunctionReturn(PETSC_SUCCESS);
3398 }
3399 
3400 /*@
3401    MatQRFactor - Performs in-place QR factorization of matrix.
3402 
3403    Collective
3404 
3405    Input Parameters:
3406 +  mat - the matrix
3407 .  col - column permutation
3408 -  info - options for factorization, includes
3409 .vb
3410           fill - expected fill as ratio of original fill.
3411           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3412                    Run with the option -info to determine an optimal value to use
3413 .ve
3414 
3415    Level: developer
3416 
3417    Notes:
3418    Most users should employ the `KSP` interface for linear solvers
3419    instead of working directly with matrix algebra routines such as this.
3420    See, e.g., `KSPCreate()`.
3421 
3422    This changes the state of the matrix to a factored matrix; it cannot be used
3423    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3424 
3425    Developer Note:
3426    The Fortran interface is not autogenerated as the
3427    interface definition cannot be generated correctly [due to MatFactorInfo]
3428 
3429 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3430           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3431 @*/
3432 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3433 {
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3436   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3437   if (info) PetscValidPointer(info, 3);
3438   PetscValidType(mat, 1);
3439   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3440   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3441   MatCheckPreallocated(mat, 1);
3442   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3443   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3444   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3445   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3446   PetscFunctionReturn(PETSC_SUCCESS);
3447 }
3448 
3449 /*@
3450    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3451    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3452 
3453    Collective
3454 
3455    Input Parameters:
3456 +  fact - the factor matrix obtained with `MatGetFactor()`
3457 .  mat - the matrix
3458 .  col - column permutation
3459 -  info - options for factorization, includes
3460 .vb
3461           fill - expected fill as ratio of original fill.
3462           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3463                    Run with the option -info to determine an optimal value to use
3464 .ve
3465 
3466    Level: developer
3467 
3468    Note:
3469    Most users should employ the `KSP` interface for linear solvers
3470    instead of working directly with matrix algebra routines such as this.
3471    See, e.g., `KSPCreate()`.
3472 
3473    Developer Note:
3474    The Fortran interface is not autogenerated as the
3475    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3476 
3477 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3478 @*/
3479 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3480 {
3481   MatFactorInfo tinfo;
3482 
3483   PetscFunctionBegin;
3484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3485   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3486   if (info) PetscValidPointer(info, 4);
3487   PetscValidType(mat, 2);
3488   PetscValidPointer(fact, 1);
3489   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3490   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3491   MatCheckPreallocated(mat, 2);
3492   if (!info) {
3493     PetscCall(MatFactorInfoInitialize(&tinfo));
3494     info = &tinfo;
3495   }
3496 
3497   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3498   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3499   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3500   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3501   PetscFunctionReturn(PETSC_SUCCESS);
3502 }
3503 
3504 /*@
3505    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3506    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3507 
3508    Collective
3509 
3510    Input Parameters:
3511 +  fact - the factor matrix obtained with `MatGetFactor()`
3512 .  mat - the matrix
3513 -  info - options for factorization
3514 
3515    Level: developer
3516 
3517    Notes:
3518    See `MatQRFactor()` for in-place factorization.
3519 
3520    Most users should employ the `KSP` interface for linear solvers
3521    instead of working directly with matrix algebra routines such as this.
3522    See, e.g., `KSPCreate()`.
3523 
3524    Developer Note:
3525    The Fortran interface is not autogenerated as the
3526    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3527 
3528 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3529 @*/
3530 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3531 {
3532   MatFactorInfo tinfo;
3533 
3534   PetscFunctionBegin;
3535   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3536   PetscValidType(mat, 2);
3537   PetscValidPointer(fact, 1);
3538   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3539   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3540   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,
3541              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3542 
3543   MatCheckPreallocated(mat, 2);
3544   if (!info) {
3545     PetscCall(MatFactorInfoInitialize(&tinfo));
3546     info = &tinfo;
3547   }
3548 
3549   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3550   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3551   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3552   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3553   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3554   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3555   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3556   PetscFunctionReturn(PETSC_SUCCESS);
3557 }
3558 
3559 /*@
3560    MatSolve - Solves A x = b, given a factored matrix.
3561 
3562    Neighbor-wise Collective
3563 
3564    Input Parameters:
3565 +  mat - the factored matrix
3566 -  b - the right-hand-side vector
3567 
3568    Output Parameter:
3569 .  x - the result vector
3570 
3571    Level: developer
3572 
3573    Notes:
3574    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3575    call `MatSolve`(A,x,x).
3576 
3577    Most users should employ the `KSP` interface for linear solvers
3578    instead of working directly with matrix algebra routines such as this.
3579    See, e.g., `KSPCreate()`.
3580 
3581 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3582 @*/
3583 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3584 {
3585   PetscFunctionBegin;
3586   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3587   PetscValidType(mat, 1);
3588   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3589   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3590   PetscCheckSameComm(mat, 1, b, 2);
3591   PetscCheckSameComm(mat, 1, x, 3);
3592   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3593   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);
3594   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);
3595   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);
3596   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3597   MatCheckPreallocated(mat, 1);
3598 
3599   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3600   if (mat->factorerrortype) {
3601     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3602     PetscCall(VecSetInf(x));
3603   } else PetscUseTypeMethod(mat, solve, b, x);
3604   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3605   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3606   PetscFunctionReturn(PETSC_SUCCESS);
3607 }
3608 
3609 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3610 {
3611   Vec      b, x;
3612   PetscInt N, i;
3613   PetscErrorCode (*f)(Mat, Vec, Vec);
3614   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3615 
3616   PetscFunctionBegin;
3617   if (A->factorerrortype) {
3618     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3619     PetscCall(MatSetInf(X));
3620     PetscFunctionReturn(PETSC_SUCCESS);
3621   }
3622   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3623   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3624   PetscCall(MatBoundToCPU(A, &Abound));
3625   if (!Abound) {
3626     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3627     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3628   }
3629 #if defined(PETSC_HAVE_CUDA)
3630   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3631   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3632 #elif (PETSC_HAVE_HIP)
3633   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3634   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3635 #endif
3636   PetscCall(MatGetSize(B, NULL, &N));
3637   for (i = 0; i < N; i++) {
3638     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3639     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3640     PetscCall((*f)(A, b, x));
3641     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3642     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3643   }
3644   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3645   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3646   PetscFunctionReturn(PETSC_SUCCESS);
3647 }
3648 
3649 /*@
3650    MatMatSolve - Solves A X = B, given a factored matrix.
3651 
3652    Neighbor-wise Collective
3653 
3654    Input Parameters:
3655 +  A - the factored matrix
3656 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3657 
3658    Output Parameter:
3659 .  X - the result matrix (dense matrix)
3660 
3661    Level: developer
3662 
3663    Note:
3664    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3665    otherwise, `B` and `X` cannot be the same.
3666 
3667 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3668 @*/
3669 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3670 {
3671   PetscFunctionBegin;
3672   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3673   PetscValidType(A, 1);
3674   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3675   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3676   PetscCheckSameComm(A, 1, B, 2);
3677   PetscCheckSameComm(A, 1, X, 3);
3678   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);
3679   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);
3680   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");
3681   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3682   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3683   MatCheckPreallocated(A, 1);
3684 
3685   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3686   if (!A->ops->matsolve) {
3687     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3688     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3689   } else PetscUseTypeMethod(A, matsolve, B, X);
3690   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3691   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3692   PetscFunctionReturn(PETSC_SUCCESS);
3693 }
3694 
3695 /*@
3696    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3697 
3698    Neighbor-wise Collective
3699 
3700    Input Parameters:
3701 +  A - the factored matrix
3702 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3703 
3704    Output Parameter:
3705 .  X - the result matrix (dense matrix)
3706 
3707    Level: developer
3708 
3709    Note:
3710    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3711    call `MatMatSolveTranspose`(A,X,X).
3712 
3713 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3714 @*/
3715 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3716 {
3717   PetscFunctionBegin;
3718   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3719   PetscValidType(A, 1);
3720   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3721   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3722   PetscCheckSameComm(A, 1, B, 2);
3723   PetscCheckSameComm(A, 1, X, 3);
3724   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3725   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);
3726   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);
3727   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);
3728   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");
3729   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3730   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3731   MatCheckPreallocated(A, 1);
3732 
3733   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3734   if (!A->ops->matsolvetranspose) {
3735     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3736     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3737   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3738   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3739   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3740   PetscFunctionReturn(PETSC_SUCCESS);
3741 }
3742 
3743 /*@
3744    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3745 
3746    Neighbor-wise Collective
3747 
3748    Input Parameters:
3749 +  A - the factored matrix
3750 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3751 
3752    Output Parameter:
3753 .  X - the result matrix (dense matrix)
3754 
3755    Level: developer
3756 
3757    Note:
3758    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
3759    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3760 
3761 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3762 @*/
3763 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3764 {
3765   PetscFunctionBegin;
3766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3767   PetscValidType(A, 1);
3768   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3769   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3770   PetscCheckSameComm(A, 1, Bt, 2);
3771   PetscCheckSameComm(A, 1, X, 3);
3772 
3773   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3774   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);
3775   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);
3776   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");
3777   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3778   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3779   MatCheckPreallocated(A, 1);
3780 
3781   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3782   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3783   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3784   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3785   PetscFunctionReturn(PETSC_SUCCESS);
3786 }
3787 
3788 /*@
3789    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3790                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3791 
3792    Neighbor-wise Collective
3793 
3794    Input Parameters:
3795 +  mat - the factored matrix
3796 -  b - the right-hand-side vector
3797 
3798    Output Parameter:
3799 .  x - the result vector
3800 
3801    Level: developer
3802 
3803    Notes:
3804    `MatSolve()` should be used for most applications, as it performs
3805    a forward solve followed by a backward solve.
3806 
3807    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3808    call `MatForwardSolve`(A,x,x).
3809 
3810    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3811    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3812    `MatForwardSolve()` solves U^T*D y = b, and
3813    `MatBackwardSolve()` solves U x = y.
3814    Thus they do not provide a symmetric preconditioner.
3815 
3816 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3817 @*/
3818 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3819 {
3820   PetscFunctionBegin;
3821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3822   PetscValidType(mat, 1);
3823   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3824   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3825   PetscCheckSameComm(mat, 1, b, 2);
3826   PetscCheckSameComm(mat, 1, x, 3);
3827   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3828   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);
3829   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);
3830   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);
3831   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3832   MatCheckPreallocated(mat, 1);
3833 
3834   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3835   PetscUseTypeMethod(mat, forwardsolve, b, x);
3836   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3837   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3838   PetscFunctionReturn(PETSC_SUCCESS);
3839 }
3840 
3841 /*@
3842    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3843                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3844 
3845    Neighbor-wise Collective
3846 
3847    Input Parameters:
3848 +  mat - the factored matrix
3849 -  b - the right-hand-side vector
3850 
3851    Output Parameter:
3852 .  x - the result vector
3853 
3854    Level: developer
3855 
3856    Notes:
3857    `MatSolve()` should be used for most applications, as it performs
3858    a forward solve followed by a backward solve.
3859 
3860    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3861    call `MatBackwardSolve`(A,x,x).
3862 
3863    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3864    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3865    `MatForwardSolve()` solves U^T*D y = b, and
3866    `MatBackwardSolve()` solves U x = y.
3867    Thus they do not provide a symmetric preconditioner.
3868 
3869 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3870 @*/
3871 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3872 {
3873   PetscFunctionBegin;
3874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3875   PetscValidType(mat, 1);
3876   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3877   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3878   PetscCheckSameComm(mat, 1, b, 2);
3879   PetscCheckSameComm(mat, 1, x, 3);
3880   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3881   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);
3882   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);
3883   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);
3884   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3885   MatCheckPreallocated(mat, 1);
3886 
3887   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3888   PetscUseTypeMethod(mat, backwardsolve, b, x);
3889   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3890   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3891   PetscFunctionReturn(PETSC_SUCCESS);
3892 }
3893 
3894 /*@
3895    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3896 
3897    Neighbor-wise Collective
3898 
3899    Input Parameters:
3900 +  mat - the factored matrix
3901 .  b - the right-hand-side vector
3902 -  y - the vector to be added to
3903 
3904    Output Parameter:
3905 .  x - the result vector
3906 
3907    Level: developer
3908 
3909    Note:
3910    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3911    call `MatSolveAdd`(A,x,y,x).
3912 
3913 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3914 @*/
3915 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3916 {
3917   PetscScalar one = 1.0;
3918   Vec         tmp;
3919 
3920   PetscFunctionBegin;
3921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3922   PetscValidType(mat, 1);
3923   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3924   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3925   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3926   PetscCheckSameComm(mat, 1, b, 2);
3927   PetscCheckSameComm(mat, 1, y, 3);
3928   PetscCheckSameComm(mat, 1, x, 4);
3929   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3930   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);
3931   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);
3932   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);
3933   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);
3934   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);
3935   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3936   MatCheckPreallocated(mat, 1);
3937 
3938   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3939   if (mat->factorerrortype) {
3940     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3941     PetscCall(VecSetInf(x));
3942   } else if (mat->ops->solveadd) {
3943     PetscUseTypeMethod(mat, solveadd, b, y, x);
3944   } else {
3945     /* do the solve then the add manually */
3946     if (x != y) {
3947       PetscCall(MatSolve(mat, b, x));
3948       PetscCall(VecAXPY(x, one, y));
3949     } else {
3950       PetscCall(VecDuplicate(x, &tmp));
3951       PetscCall(VecCopy(x, tmp));
3952       PetscCall(MatSolve(mat, b, x));
3953       PetscCall(VecAXPY(x, one, tmp));
3954       PetscCall(VecDestroy(&tmp));
3955     }
3956   }
3957   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3958   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3959   PetscFunctionReturn(PETSC_SUCCESS);
3960 }
3961 
3962 /*@
3963    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3964 
3965    Neighbor-wise Collective
3966 
3967    Input Parameters:
3968 +  mat - the factored matrix
3969 -  b - the right-hand-side vector
3970 
3971    Output Parameter:
3972 .  x - the result vector
3973 
3974    Level: developer
3975 
3976    Notes:
3977    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3978    call `MatSolveTranspose`(A,x,x).
3979 
3980    Most users should employ the `KSP` interface for linear solvers
3981    instead of working directly with matrix algebra routines such as this.
3982    See, e.g., `KSPCreate()`.
3983 
3984 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3985 @*/
3986 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3987 {
3988   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3989 
3990   PetscFunctionBegin;
3991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3992   PetscValidType(mat, 1);
3993   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3994   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3995   PetscCheckSameComm(mat, 1, b, 2);
3996   PetscCheckSameComm(mat, 1, x, 3);
3997   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3998   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);
3999   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);
4000   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4001   MatCheckPreallocated(mat, 1);
4002   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4003   if (mat->factorerrortype) {
4004     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4005     PetscCall(VecSetInf(x));
4006   } else {
4007     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4008     PetscCall((*f)(mat, b, x));
4009   }
4010   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4011   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4012   PetscFunctionReturn(PETSC_SUCCESS);
4013 }
4014 
4015 /*@
4016    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4017                       factored matrix.
4018 
4019    Neighbor-wise Collective
4020 
4021    Input Parameters:
4022 +  mat - the factored matrix
4023 .  b - the right-hand-side vector
4024 -  y - the vector to be added to
4025 
4026    Output Parameter:
4027 .  x - the result vector
4028 
4029    Level: developer
4030 
4031    Note:
4032    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4033    call `MatSolveTransposeAdd`(A,x,y,x).
4034 
4035 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4036 @*/
4037 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4038 {
4039   PetscScalar one = 1.0;
4040   Vec         tmp;
4041   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4042 
4043   PetscFunctionBegin;
4044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4045   PetscValidType(mat, 1);
4046   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4047   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4048   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4049   PetscCheckSameComm(mat, 1, b, 2);
4050   PetscCheckSameComm(mat, 1, y, 3);
4051   PetscCheckSameComm(mat, 1, x, 4);
4052   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4053   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);
4054   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);
4055   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);
4056   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);
4057   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4058   MatCheckPreallocated(mat, 1);
4059 
4060   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4061   if (mat->factorerrortype) {
4062     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4063     PetscCall(VecSetInf(x));
4064   } else if (f) {
4065     PetscCall((*f)(mat, b, y, x));
4066   } else {
4067     /* do the solve then the add manually */
4068     if (x != y) {
4069       PetscCall(MatSolveTranspose(mat, b, x));
4070       PetscCall(VecAXPY(x, one, y));
4071     } else {
4072       PetscCall(VecDuplicate(x, &tmp));
4073       PetscCall(VecCopy(x, tmp));
4074       PetscCall(MatSolveTranspose(mat, b, x));
4075       PetscCall(VecAXPY(x, one, tmp));
4076       PetscCall(VecDestroy(&tmp));
4077     }
4078   }
4079   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4080   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4081   PetscFunctionReturn(PETSC_SUCCESS);
4082 }
4083 
4084 /*@
4085    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4086 
4087    Neighbor-wise Collective
4088 
4089    Input Parameters:
4090 +  mat - the matrix
4091 .  b - the right hand side
4092 .  omega - the relaxation factor
4093 .  flag - flag indicating the type of SOR (see below)
4094 .  shift -  diagonal shift
4095 .  its - the number of iterations
4096 -  lits - the number of local iterations
4097 
4098    Output Parameter:
4099 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4100 
4101    SOR Flags:
4102 +     `SOR_FORWARD_SWEEP` - forward SOR
4103 .     `SOR_BACKWARD_SWEEP` - backward SOR
4104 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4105 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4106 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4107 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4108 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4109 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4110          upper/lower triangular part of matrix to
4111          vector (with omega)
4112 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4113 
4114    Level: developer
4115 
4116    Notes:
4117    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4118    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4119    on each processor.
4120 
4121    Application programmers will not generally use `MatSOR()` directly,
4122    but instead will employ the `KSP`/`PC` interface.
4123 
4124    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4125 
4126    Most users should employ the `KSP` interface for linear solvers
4127    instead of working directly with matrix algebra routines such as this.
4128    See, e.g., `KSPCreate()`.
4129 
4130    Vectors `x` and `b` CANNOT be the same
4131 
4132    The flags are implemented as bitwise inclusive or operations.
4133    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4134    to specify a zero initial guess for SSOR.
4135 
4136    Developer Note:
4137    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4138 
4139 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4140 @*/
4141 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4142 {
4143   PetscFunctionBegin;
4144   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4145   PetscValidType(mat, 1);
4146   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4147   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4148   PetscCheckSameComm(mat, 1, b, 2);
4149   PetscCheckSameComm(mat, 1, x, 8);
4150   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4151   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4152   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);
4153   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);
4154   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);
4155   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4156   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4157   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4158 
4159   MatCheckPreallocated(mat, 1);
4160   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4161   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4162   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4163   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4164   PetscFunctionReturn(PETSC_SUCCESS);
4165 }
4166 
4167 /*
4168       Default matrix copy routine.
4169 */
4170 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4171 {
4172   PetscInt           i, rstart = 0, rend = 0, nz;
4173   const PetscInt    *cwork;
4174   const PetscScalar *vwork;
4175 
4176   PetscFunctionBegin;
4177   if (B->assembled) PetscCall(MatZeroEntries(B));
4178   if (str == SAME_NONZERO_PATTERN) {
4179     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4180     for (i = rstart; i < rend; i++) {
4181       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4182       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4183       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4184     }
4185   } else {
4186     PetscCall(MatAYPX(B, 0.0, A, str));
4187   }
4188   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4189   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4190   PetscFunctionReturn(PETSC_SUCCESS);
4191 }
4192 
4193 /*@
4194    MatCopy - Copies a matrix to another matrix.
4195 
4196    Collective
4197 
4198    Input Parameters:
4199 +  A - the matrix
4200 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4201 
4202    Output Parameter:
4203 .  B - where the copy is put
4204 
4205    Level: intermediate
4206 
4207    Notes:
4208    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4209 
4210    `MatCopy()` copies the matrix entries of a matrix to another existing
4211    matrix (after first zeroing the second matrix).  A related routine is
4212    `MatConvert()`, which first creates a new matrix and then copies the data.
4213 
4214 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4215 @*/
4216 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4217 {
4218   PetscInt i;
4219 
4220   PetscFunctionBegin;
4221   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4222   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4223   PetscValidType(A, 1);
4224   PetscValidType(B, 2);
4225   PetscCheckSameComm(A, 1, B, 2);
4226   MatCheckPreallocated(B, 2);
4227   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4228   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4229   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,
4230              A->cmap->N, B->cmap->N);
4231   MatCheckPreallocated(A, 1);
4232   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4233 
4234   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4235   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4236   else PetscCall(MatCopy_Basic(A, B, str));
4237 
4238   B->stencil.dim = A->stencil.dim;
4239   B->stencil.noc = A->stencil.noc;
4240   for (i = 0; i <= A->stencil.dim; i++) {
4241     B->stencil.dims[i]   = A->stencil.dims[i];
4242     B->stencil.starts[i] = A->stencil.starts[i];
4243   }
4244 
4245   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4246   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4247   PetscFunctionReturn(PETSC_SUCCESS);
4248 }
4249 
4250 /*@C
4251    MatConvert - Converts a matrix to another matrix, either of the same
4252    or different type.
4253 
4254    Collective
4255 
4256    Input Parameters:
4257 +  mat - the matrix
4258 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4259    same type as the original matrix.
4260 -  reuse - denotes if the destination matrix is to be created or reused.
4261    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
4262    `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).
4263 
4264    Output Parameter:
4265 .  M - pointer to place new matrix
4266 
4267    Level: intermediate
4268 
4269    Notes:
4270    `MatConvert()` first creates a new matrix and then copies the data from
4271    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4272    entries of one matrix to another already existing matrix context.
4273 
4274    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4275    the MPI communicator of the generated matrix is always the same as the communicator
4276    of the input matrix.
4277 
4278 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4279 @*/
4280 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4281 {
4282   PetscBool  sametype, issame, flg;
4283   PetscBool3 issymmetric, ishermitian;
4284   char       convname[256], mtype[256];
4285   Mat        B;
4286 
4287   PetscFunctionBegin;
4288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4289   PetscValidType(mat, 1);
4290   PetscValidPointer(M, 4);
4291   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4292   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4293   MatCheckPreallocated(mat, 1);
4294 
4295   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4296   if (flg) newtype = mtype;
4297 
4298   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4299   PetscCall(PetscStrcmp(newtype, "same", &issame));
4300   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4301   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");
4302 
4303   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4304     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4305     PetscFunctionReturn(PETSC_SUCCESS);
4306   }
4307 
4308   /* Cache Mat options because some converters use MatHeaderReplace  */
4309   issymmetric = mat->symmetric;
4310   ishermitian = mat->hermitian;
4311 
4312   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4313     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4314     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4315   } else {
4316     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4317     const char *prefix[3]                                 = {"seq", "mpi", ""};
4318     PetscInt    i;
4319     /*
4320        Order of precedence:
4321        0) See if newtype is a superclass of the current matrix.
4322        1) See if a specialized converter is known to the current matrix.
4323        2) See if a specialized converter is known to the desired matrix class.
4324        3) See if a good general converter is registered for the desired class
4325           (as of 6/27/03 only MATMPIADJ falls into this category).
4326        4) See if a good general converter is known for the current matrix.
4327        5) Use a really basic converter.
4328     */
4329 
4330     /* 0) See if newtype is a superclass of the current matrix.
4331           i.e mat is mpiaij and newtype is aij */
4332     for (i = 0; i < 2; i++) {
4333       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4334       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4335       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4336       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4337       if (flg) {
4338         if (reuse == MAT_INPLACE_MATRIX) {
4339           PetscCall(PetscInfo(mat, "Early return\n"));
4340           PetscFunctionReturn(PETSC_SUCCESS);
4341         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4342           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4343           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4344           PetscFunctionReturn(PETSC_SUCCESS);
4345         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4346           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4347           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4348           PetscFunctionReturn(PETSC_SUCCESS);
4349         }
4350       }
4351     }
4352     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4353     for (i = 0; i < 3; i++) {
4354       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4355       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4357       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4358       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4360       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4361       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4362       if (conv) goto foundconv;
4363     }
4364 
4365     /* 2)  See if a specialized converter is known to the desired matrix class. */
4366     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4367     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4368     PetscCall(MatSetType(B, newtype));
4369     for (i = 0; i < 3; i++) {
4370       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4371       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4372       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4376       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4377       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4378       if (conv) {
4379         PetscCall(MatDestroy(&B));
4380         goto foundconv;
4381       }
4382     }
4383 
4384     /* 3) See if a good general converter is registered for the desired class */
4385     conv = B->ops->convertfrom;
4386     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4387     PetscCall(MatDestroy(&B));
4388     if (conv) goto foundconv;
4389 
4390     /* 4) See if a good general converter is known for the current matrix */
4391     if (mat->ops->convert) conv = mat->ops->convert;
4392     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4393     if (conv) goto foundconv;
4394 
4395     /* 5) Use a really basic converter. */
4396     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4397     conv = MatConvert_Basic;
4398 
4399   foundconv:
4400     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4401     PetscCall((*conv)(mat, newtype, reuse, M));
4402     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4403       /* the block sizes must be same if the mappings are copied over */
4404       (*M)->rmap->bs = mat->rmap->bs;
4405       (*M)->cmap->bs = mat->cmap->bs;
4406       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4407       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4408       (*M)->rmap->mapping = mat->rmap->mapping;
4409       (*M)->cmap->mapping = mat->cmap->mapping;
4410     }
4411     (*M)->stencil.dim = mat->stencil.dim;
4412     (*M)->stencil.noc = mat->stencil.noc;
4413     for (i = 0; i <= mat->stencil.dim; i++) {
4414       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4415       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4416     }
4417     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4418   }
4419   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4420 
4421   /* Copy Mat options */
4422   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4423   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4424   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4425   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4426   PetscFunctionReturn(PETSC_SUCCESS);
4427 }
4428 
4429 /*@C
4430    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4431 
4432    Not Collective
4433 
4434    Input Parameter:
4435 .  mat - the matrix, must be a factored matrix
4436 
4437    Output Parameter:
4438 .   type - the string name of the package (do not free this string)
4439 
4440    Level: intermediate
4441 
4442    Fortran Note:
4443    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4444 
4445 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4446 @*/
4447 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4448 {
4449   PetscErrorCode (*conv)(Mat, MatSolverType *);
4450 
4451   PetscFunctionBegin;
4452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4453   PetscValidType(mat, 1);
4454   PetscValidPointer(type, 2);
4455   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4456   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4457   if (conv) PetscCall((*conv)(mat, type));
4458   else *type = MATSOLVERPETSC;
4459   PetscFunctionReturn(PETSC_SUCCESS);
4460 }
4461 
4462 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4463 struct _MatSolverTypeForSpecifcType {
4464   MatType mtype;
4465   /* no entry for MAT_FACTOR_NONE */
4466   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4467   MatSolverTypeForSpecifcType next;
4468 };
4469 
4470 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4471 struct _MatSolverTypeHolder {
4472   char                       *name;
4473   MatSolverTypeForSpecifcType handlers;
4474   MatSolverTypeHolder         next;
4475 };
4476 
4477 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4478 
4479 /*@C
4480    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4481 
4482    Input Parameters:
4483 +    package - name of the package, for example petsc or superlu
4484 .    mtype - the matrix type that works with this package
4485 .    ftype - the type of factorization supported by the package
4486 -    createfactor - routine that will create the factored matrix ready to be used
4487 
4488     Level: developer
4489 
4490 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4491 @*/
4492 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4493 {
4494   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4495   PetscBool                   flg;
4496   MatSolverTypeForSpecifcType inext, iprev = NULL;
4497 
4498   PetscFunctionBegin;
4499   PetscCall(MatInitializePackage());
4500   if (!next) {
4501     PetscCall(PetscNew(&MatSolverTypeHolders));
4502     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4503     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4504     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4505     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4506     PetscFunctionReturn(PETSC_SUCCESS);
4507   }
4508   while (next) {
4509     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4510     if (flg) {
4511       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4512       inext = next->handlers;
4513       while (inext) {
4514         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4515         if (flg) {
4516           inext->createfactor[(int)ftype - 1] = createfactor;
4517           PetscFunctionReturn(PETSC_SUCCESS);
4518         }
4519         iprev = inext;
4520         inext = inext->next;
4521       }
4522       PetscCall(PetscNew(&iprev->next));
4523       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4524       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4525       PetscFunctionReturn(PETSC_SUCCESS);
4526     }
4527     prev = next;
4528     next = next->next;
4529   }
4530   PetscCall(PetscNew(&prev->next));
4531   PetscCall(PetscStrallocpy(package, &prev->next->name));
4532   PetscCall(PetscNew(&prev->next->handlers));
4533   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4534   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4535   PetscFunctionReturn(PETSC_SUCCESS);
4536 }
4537 
4538 /*@C
4539    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4540 
4541    Input Parameters:
4542 +    type - name of the package, for example petsc or superlu
4543 .    ftype - the type of factorization supported by the type
4544 -    mtype - the matrix type that works with this type
4545 
4546    Output Parameters:
4547 +   foundtype - `PETSC_TRUE` if the type was registered
4548 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4549 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4550 
4551     Level: developer
4552 
4553 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4554 @*/
4555 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4556 {
4557   MatSolverTypeHolder         next = MatSolverTypeHolders;
4558   PetscBool                   flg;
4559   MatSolverTypeForSpecifcType inext;
4560 
4561   PetscFunctionBegin;
4562   if (foundtype) *foundtype = PETSC_FALSE;
4563   if (foundmtype) *foundmtype = PETSC_FALSE;
4564   if (createfactor) *createfactor = NULL;
4565 
4566   if (type) {
4567     while (next) {
4568       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4569       if (flg) {
4570         if (foundtype) *foundtype = PETSC_TRUE;
4571         inext = next->handlers;
4572         while (inext) {
4573           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4574           if (flg) {
4575             if (foundmtype) *foundmtype = PETSC_TRUE;
4576             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4577             PetscFunctionReturn(PETSC_SUCCESS);
4578           }
4579           inext = inext->next;
4580         }
4581       }
4582       next = next->next;
4583     }
4584   } else {
4585     while (next) {
4586       inext = next->handlers;
4587       while (inext) {
4588         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4589         if (flg && inext->createfactor[(int)ftype - 1]) {
4590           if (foundtype) *foundtype = PETSC_TRUE;
4591           if (foundmtype) *foundmtype = PETSC_TRUE;
4592           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4593           PetscFunctionReturn(PETSC_SUCCESS);
4594         }
4595         inext = inext->next;
4596       }
4597       next = next->next;
4598     }
4599     /* try with base classes inext->mtype */
4600     next = MatSolverTypeHolders;
4601     while (next) {
4602       inext = next->handlers;
4603       while (inext) {
4604         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4605         if (flg && inext->createfactor[(int)ftype - 1]) {
4606           if (foundtype) *foundtype = PETSC_TRUE;
4607           if (foundmtype) *foundmtype = PETSC_TRUE;
4608           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4609           PetscFunctionReturn(PETSC_SUCCESS);
4610         }
4611         inext = inext->next;
4612       }
4613       next = next->next;
4614     }
4615   }
4616   PetscFunctionReturn(PETSC_SUCCESS);
4617 }
4618 
4619 PetscErrorCode MatSolverTypeDestroy(void)
4620 {
4621   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4622   MatSolverTypeForSpecifcType inext, iprev;
4623 
4624   PetscFunctionBegin;
4625   while (next) {
4626     PetscCall(PetscFree(next->name));
4627     inext = next->handlers;
4628     while (inext) {
4629       PetscCall(PetscFree(inext->mtype));
4630       iprev = inext;
4631       inext = inext->next;
4632       PetscCall(PetscFree(iprev));
4633     }
4634     prev = next;
4635     next = next->next;
4636     PetscCall(PetscFree(prev));
4637   }
4638   MatSolverTypeHolders = NULL;
4639   PetscFunctionReturn(PETSC_SUCCESS);
4640 }
4641 
4642 /*@C
4643    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4644 
4645    Logically Collective
4646 
4647    Input Parameters:
4648 .  mat - the matrix
4649 
4650    Output Parameter:
4651 .  flg - `PETSC_TRUE` if uses the ordering
4652 
4653    Level: developer
4654 
4655    Note:
4656    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4657    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4658 
4659 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4660 @*/
4661 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4662 {
4663   PetscFunctionBegin;
4664   *flg = mat->canuseordering;
4665   PetscFunctionReturn(PETSC_SUCCESS);
4666 }
4667 
4668 /*@C
4669    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4670 
4671    Logically Collective
4672 
4673    Input Parameters:
4674 +  mat - the matrix obtained with `MatGetFactor()`
4675 -  ftype - the factorization type to be used
4676 
4677    Output Parameter:
4678 .  otype - the preferred ordering type
4679 
4680    Level: developer
4681 
4682 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4683 @*/
4684 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4685 {
4686   PetscFunctionBegin;
4687   *otype = mat->preferredordering[ftype];
4688   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4689   PetscFunctionReturn(PETSC_SUCCESS);
4690 }
4691 
4692 /*@C
4693    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4694 
4695    Collective
4696 
4697    Input Parameters:
4698 +  mat - the matrix
4699 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4700 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4701 
4702    Output Parameter:
4703 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4704 
4705    Options Database Key:
4706 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4707                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4708 
4709    Level: intermediate
4710 
4711    Notes:
4712      Users usually access the factorization solvers via `KSP`
4713 
4714       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4715      such as pastix, superlu, mumps etc.
4716 
4717       PETSc must have been ./configure to use the external solver, using the option --download-package
4718 
4719       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4720       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4721       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4722 
4723    Developer Note:
4724       This should actually be called `MatCreateFactor()` since it creates a new factor object
4725 
4726 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4727           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4728 @*/
4729 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4730 {
4731   PetscBool foundtype, foundmtype;
4732   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4733 
4734   PetscFunctionBegin;
4735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4736   PetscValidType(mat, 1);
4737 
4738   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4739   MatCheckPreallocated(mat, 1);
4740 
4741   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4742   if (!foundtype) {
4743     if (type) {
4744       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],
4745               ((PetscObject)mat)->type_name, type);
4746     } else {
4747       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);
4748     }
4749   }
4750   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4751   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);
4752 
4753   PetscCall((*conv)(mat, ftype, f));
4754   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4755   PetscFunctionReturn(PETSC_SUCCESS);
4756 }
4757 
4758 /*@C
4759    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4760 
4761    Not Collective
4762 
4763    Input Parameters:
4764 +  mat - the matrix
4765 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4766 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4767 
4768    Output Parameter:
4769 .    flg - PETSC_TRUE if the factorization is available
4770 
4771    Level: intermediate
4772 
4773    Notes:
4774       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4775      such as pastix, superlu, mumps etc.
4776 
4777       PETSc must have been ./configure to use the external solver, using the option --download-package
4778 
4779    Developer Note:
4780       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4781 
4782 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4783           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4784 @*/
4785 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4786 {
4787   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4788 
4789   PetscFunctionBegin;
4790   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4791   PetscValidType(mat, 1);
4792   PetscValidBoolPointer(flg, 4);
4793 
4794   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4795   MatCheckPreallocated(mat, 1);
4796 
4797   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4798   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4799   PetscFunctionReturn(PETSC_SUCCESS);
4800 }
4801 
4802 /*@
4803    MatDuplicate - Duplicates a matrix including the non-zero structure.
4804 
4805    Collective
4806 
4807    Input Parameters:
4808 +  mat - the matrix
4809 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4810         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4811 
4812    Output Parameter:
4813 .  M - pointer to place new matrix
4814 
4815    Level: intermediate
4816 
4817    Notes:
4818     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4819 
4820     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.
4821 
4822     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
4823     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4824     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4825 
4826 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4827 @*/
4828 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4829 {
4830   Mat         B;
4831   VecType     vtype;
4832   PetscInt    i;
4833   PetscObject dm;
4834   void (*viewf)(void);
4835 
4836   PetscFunctionBegin;
4837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4838   PetscValidType(mat, 1);
4839   PetscValidPointer(M, 3);
4840   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4841   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4842   MatCheckPreallocated(mat, 1);
4843 
4844   *M = NULL;
4845   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4846   PetscUseTypeMethod(mat, duplicate, op, M);
4847   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4848   B = *M;
4849 
4850   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4851   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4852   PetscCall(MatGetVecType(mat, &vtype));
4853   PetscCall(MatSetVecType(B, vtype));
4854 
4855   B->stencil.dim = mat->stencil.dim;
4856   B->stencil.noc = mat->stencil.noc;
4857   for (i = 0; i <= mat->stencil.dim; i++) {
4858     B->stencil.dims[i]   = mat->stencil.dims[i];
4859     B->stencil.starts[i] = mat->stencil.starts[i];
4860   }
4861 
4862   B->nooffproczerorows = mat->nooffproczerorows;
4863   B->nooffprocentries  = mat->nooffprocentries;
4864 
4865   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4866   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4867   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4868   PetscFunctionReturn(PETSC_SUCCESS);
4869 }
4870 
4871 /*@
4872    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4873 
4874    Logically Collective
4875 
4876    Input Parameters:
4877 .  mat - the matrix
4878 
4879    Output Parameter:
4880 .  v - the diagonal of the matrix
4881 
4882    Level: intermediate
4883 
4884    Note:
4885    Currently only correct in parallel for square matrices.
4886 
4887 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4888 @*/
4889 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4890 {
4891   PetscFunctionBegin;
4892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4893   PetscValidType(mat, 1);
4894   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4895   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4896   MatCheckPreallocated(mat, 1);
4897 
4898   PetscUseTypeMethod(mat, getdiagonal, v);
4899   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4900   PetscFunctionReturn(PETSC_SUCCESS);
4901 }
4902 
4903 /*@C
4904    MatGetRowMin - Gets the minimum value (of the real part) of each
4905         row of the matrix
4906 
4907    Logically Collective
4908 
4909    Input Parameter:
4910 .  mat - the matrix
4911 
4912    Output Parameters:
4913 +  v - the vector for storing the maximums
4914 -  idx - the indices of the column found for each row (optional)
4915 
4916    Level: intermediate
4917 
4918    Note:
4919     The result of this call are the same as if one converted the matrix to dense format
4920       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4921 
4922     This code is only implemented for a couple of matrix formats.
4923 
4924 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4925           `MatGetRowMax()`
4926 @*/
4927 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4928 {
4929   PetscFunctionBegin;
4930   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4931   PetscValidType(mat, 1);
4932   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4933   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4934 
4935   if (!mat->cmap->N) {
4936     PetscCall(VecSet(v, PETSC_MAX_REAL));
4937     if (idx) {
4938       PetscInt i, m = mat->rmap->n;
4939       for (i = 0; i < m; i++) idx[i] = -1;
4940     }
4941   } else {
4942     MatCheckPreallocated(mat, 1);
4943   }
4944   PetscUseTypeMethod(mat, getrowmin, v, idx);
4945   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4946   PetscFunctionReturn(PETSC_SUCCESS);
4947 }
4948 
4949 /*@C
4950    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4951         row of the matrix
4952 
4953    Logically Collective
4954 
4955    Input Parameter:
4956 .  mat - the matrix
4957 
4958    Output Parameters:
4959 +  v - the vector for storing the minimums
4960 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4961 
4962    Level: intermediate
4963 
4964    Notes:
4965     if a row is completely empty or has only 0.0 values then the idx[] value for that
4966     row is 0 (the first column).
4967 
4968     This code is only implemented for a couple of matrix formats.
4969 
4970 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4971 @*/
4972 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4973 {
4974   PetscFunctionBegin;
4975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4976   PetscValidType(mat, 1);
4977   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4978   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4979   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4980 
4981   if (!mat->cmap->N) {
4982     PetscCall(VecSet(v, 0.0));
4983     if (idx) {
4984       PetscInt i, m = mat->rmap->n;
4985       for (i = 0; i < m; i++) idx[i] = -1;
4986     }
4987   } else {
4988     MatCheckPreallocated(mat, 1);
4989     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4990     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4991   }
4992   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4993   PetscFunctionReturn(PETSC_SUCCESS);
4994 }
4995 
4996 /*@C
4997    MatGetRowMax - Gets the maximum value (of the real part) of each
4998         row of the matrix
4999 
5000    Logically Collective
5001 
5002    Input Parameter:
5003 .  mat - the matrix
5004 
5005    Output Parameters:
5006 +  v - the vector for storing the maximums
5007 -  idx - the indices of the column found for each row (optional)
5008 
5009    Level: intermediate
5010 
5011    Notes:
5012     The result of this call are the same as if one converted the matrix to dense format
5013       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5014 
5015     This code is only implemented for a couple of matrix formats.
5016 
5017 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5018 @*/
5019 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5020 {
5021   PetscFunctionBegin;
5022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5023   PetscValidType(mat, 1);
5024   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5025   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5026 
5027   if (!mat->cmap->N) {
5028     PetscCall(VecSet(v, PETSC_MIN_REAL));
5029     if (idx) {
5030       PetscInt i, m = mat->rmap->n;
5031       for (i = 0; i < m; i++) idx[i] = -1;
5032     }
5033   } else {
5034     MatCheckPreallocated(mat, 1);
5035     PetscUseTypeMethod(mat, getrowmax, v, idx);
5036   }
5037   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5038   PetscFunctionReturn(PETSC_SUCCESS);
5039 }
5040 
5041 /*@C
5042    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5043         row of the matrix
5044 
5045    Logically Collective
5046 
5047    Input Parameter:
5048 .  mat - the matrix
5049 
5050    Output Parameters:
5051 +  v - the vector for storing the maximums
5052 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5053 
5054    Level: intermediate
5055 
5056    Notes:
5057     if a row is completely empty or has only 0.0 values then the idx[] value for that
5058     row is 0 (the first column).
5059 
5060     This code is only implemented for a couple of matrix formats.
5061 
5062 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5063 @*/
5064 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5065 {
5066   PetscFunctionBegin;
5067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5068   PetscValidType(mat, 1);
5069   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5071 
5072   if (!mat->cmap->N) {
5073     PetscCall(VecSet(v, 0.0));
5074     if (idx) {
5075       PetscInt i, m = mat->rmap->n;
5076       for (i = 0; i < m; i++) idx[i] = -1;
5077     }
5078   } else {
5079     MatCheckPreallocated(mat, 1);
5080     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5081     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5082   }
5083   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5084   PetscFunctionReturn(PETSC_SUCCESS);
5085 }
5086 
5087 /*@
5088    MatGetRowSum - Gets the sum of each row of the matrix
5089 
5090    Logically or Neighborhood Collective
5091 
5092    Input Parameters:
5093 .  mat - the matrix
5094 
5095    Output Parameter:
5096 .  v - the vector for storing the sum of rows
5097 
5098    Level: intermediate
5099 
5100    Notes:
5101     This code is slow since it is not currently specialized for different formats
5102 
5103 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5104 @*/
5105 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5106 {
5107   Vec ones;
5108 
5109   PetscFunctionBegin;
5110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5111   PetscValidType(mat, 1);
5112   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5113   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5114   MatCheckPreallocated(mat, 1);
5115   PetscCall(MatCreateVecs(mat, &ones, NULL));
5116   PetscCall(VecSet(ones, 1.));
5117   PetscCall(MatMult(mat, ones, v));
5118   PetscCall(VecDestroy(&ones));
5119   PetscFunctionReturn(PETSC_SUCCESS);
5120 }
5121 
5122 /*@
5123    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5124    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5125 
5126    Collective
5127 
5128    Input Parameter:
5129 .  mat - the matrix to provide the transpose
5130 
5131    Output Parameter:
5132 .  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
5133 
5134    Level: advanced
5135 
5136    Note:
5137    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
5138    routine allows bypassing that call.
5139 
5140 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5141 @*/
5142 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5143 {
5144   PetscContainer  rB = NULL;
5145   MatParentState *rb = NULL;
5146 
5147   PetscFunctionBegin;
5148   PetscCall(PetscNew(&rb));
5149   rb->id    = ((PetscObject)mat)->id;
5150   rb->state = 0;
5151   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5152   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5153   PetscCall(PetscContainerSetPointer(rB, rb));
5154   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5155   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5156   PetscCall(PetscObjectDereference((PetscObject)rB));
5157   PetscFunctionReturn(PETSC_SUCCESS);
5158 }
5159 
5160 /*@
5161    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5162 
5163    Collective
5164 
5165    Input Parameters:
5166 +  mat - the matrix to transpose
5167 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5168 
5169    Output Parameter:
5170 .  B - the transpose
5171 
5172    Level: intermediate
5173 
5174    Notes:
5175      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5176 
5177      `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
5178      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5179 
5180      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.
5181 
5182      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5183 
5184      If mat is unchanged from the last call this function returns immediately without recomputing the result
5185 
5186      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5187 
5188 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5189           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5190 @*/
5191 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5192 {
5193   PetscContainer  rB = NULL;
5194   MatParentState *rb = NULL;
5195 
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5198   PetscValidType(mat, 1);
5199   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5200   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5201   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5202   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5203   MatCheckPreallocated(mat, 1);
5204   if (reuse == MAT_REUSE_MATRIX) {
5205     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5206     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5207     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5208     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5209     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5210   }
5211 
5212   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5213   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5214     PetscUseTypeMethod(mat, transpose, reuse, B);
5215     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5216   }
5217   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5218 
5219   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5220   if (reuse != MAT_INPLACE_MATRIX) {
5221     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5222     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5223     rb->state        = ((PetscObject)mat)->state;
5224     rb->nonzerostate = mat->nonzerostate;
5225   }
5226   PetscFunctionReturn(PETSC_SUCCESS);
5227 }
5228 
5229 /*@
5230    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5231 
5232    Collective
5233 
5234    Input Parameters:
5235 .  A - the matrix to transpose
5236 
5237    Output Parameter:
5238 .  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
5239       numerical portion.
5240 
5241    Level: intermediate
5242 
5243    Note:
5244    This is not supported for many matrix types, use `MatTranspose()` in those cases
5245 
5246 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5247 @*/
5248 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5249 {
5250   PetscFunctionBegin;
5251   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5252   PetscValidType(A, 1);
5253   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5254   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5255   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5256   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5257   PetscCall((*A->ops->transposesymbolic)(A, B));
5258   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5259 
5260   PetscCall(MatTransposeSetPrecursor(A, *B));
5261   PetscFunctionReturn(PETSC_SUCCESS);
5262 }
5263 
5264 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5265 {
5266   PetscContainer  rB;
5267   MatParentState *rb;
5268 
5269   PetscFunctionBegin;
5270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5271   PetscValidType(A, 1);
5272   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5273   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5274   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5275   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5276   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5277   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5278   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5279   PetscFunctionReturn(PETSC_SUCCESS);
5280 }
5281 
5282 /*@
5283    MatIsTranspose - Test whether a matrix is another one's transpose,
5284         or its own, in which case it tests symmetry.
5285 
5286    Collective
5287 
5288    Input Parameters:
5289 +  A - the matrix to test
5290 .  B - the matrix to test against, this can equal the first parameter
5291 -  tol - tolerance, differences between entries smaller than this are counted as zero
5292 
5293    Output Parameter:
5294 .  flg - the result
5295 
5296    Level: intermediate
5297 
5298    Notes:
5299    Only available for `MATAIJ` matrices.
5300 
5301    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5302    test involves parallel copies of the block-offdiagonal parts of the matrix.
5303 
5304 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5305 @*/
5306 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5307 {
5308   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5309 
5310   PetscFunctionBegin;
5311   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5312   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5313   PetscValidBoolPointer(flg, 4);
5314   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5315   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5316   *flg = PETSC_FALSE;
5317   if (f && g) {
5318     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5319     PetscCall((*f)(A, B, tol, flg));
5320   } else {
5321     MatType mattype;
5322 
5323     PetscCall(MatGetType(f ? B : A, &mattype));
5324     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5325   }
5326   PetscFunctionReturn(PETSC_SUCCESS);
5327 }
5328 
5329 /*@
5330    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5331 
5332    Collective
5333 
5334    Input Parameters:
5335 +  mat - the matrix to transpose and complex conjugate
5336 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5337 
5338    Output Parameter:
5339 .  B - the Hermitian transpose
5340 
5341    Level: intermediate
5342 
5343 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5344 @*/
5345 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5346 {
5347   PetscFunctionBegin;
5348   PetscCall(MatTranspose(mat, reuse, B));
5349 #if defined(PETSC_USE_COMPLEX)
5350   PetscCall(MatConjugate(*B));
5351 #endif
5352   PetscFunctionReturn(PETSC_SUCCESS);
5353 }
5354 
5355 /*@
5356    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5357 
5358    Collective
5359 
5360    Input Parameters:
5361 +  A - the matrix to test
5362 .  B - the matrix to test against, this can equal the first parameter
5363 -  tol - tolerance, differences between entries smaller than this are counted as zero
5364 
5365    Output Parameter:
5366 .  flg - the result
5367 
5368    Level: intermediate
5369 
5370    Notes:
5371    Only available for `MATAIJ` matrices.
5372 
5373    The sequential algorithm
5374    has a running time of the order of the number of nonzeros; the parallel
5375    test involves parallel copies of the block-offdiagonal parts of the matrix.
5376 
5377 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5378 @*/
5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5380 {
5381   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5382 
5383   PetscFunctionBegin;
5384   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5385   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5386   PetscValidBoolPointer(flg, 4);
5387   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5388   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5389   if (f && g) {
5390     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5391     PetscCall((*f)(A, B, tol, flg));
5392   }
5393   PetscFunctionReturn(PETSC_SUCCESS);
5394 }
5395 
5396 /*@
5397    MatPermute - Creates a new matrix with rows and columns permuted from the
5398    original.
5399 
5400    Collective
5401 
5402    Input Parameters:
5403 +  mat - the matrix to permute
5404 .  row - row permutation, each processor supplies only the permutation for its rows
5405 -  col - column permutation, each processor supplies only the permutation for its columns
5406 
5407    Output Parameter:
5408 .  B - the permuted matrix
5409 
5410    Level: advanced
5411 
5412    Note:
5413    The index sets map from row/col of permuted matrix to row/col of original matrix.
5414    The index sets should be on the same communicator as mat and have the same local sizes.
5415 
5416    Developer Note:
5417      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5418      exploit the fact that row and col are permutations, consider implementing the
5419      more general `MatCreateSubMatrix()` instead.
5420 
5421 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5422 @*/
5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5424 {
5425   PetscFunctionBegin;
5426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5427   PetscValidType(mat, 1);
5428   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5429   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5430   PetscValidPointer(B, 4);
5431   PetscCheckSameComm(mat, 1, row, 2);
5432   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5435   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5436   MatCheckPreallocated(mat, 1);
5437 
5438   if (mat->ops->permute) {
5439     PetscUseTypeMethod(mat, permute, row, col, B);
5440     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5441   } else {
5442     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5443   }
5444   PetscFunctionReturn(PETSC_SUCCESS);
5445 }
5446 
5447 /*@
5448    MatEqual - Compares two matrices.
5449 
5450    Collective
5451 
5452    Input Parameters:
5453 +  A - the first matrix
5454 -  B - the second matrix
5455 
5456    Output Parameter:
5457 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5458 
5459    Level: intermediate
5460 
5461 .seealso: [](chapter_matrices), `Mat`
5462 @*/
5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5464 {
5465   PetscFunctionBegin;
5466   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5467   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5468   PetscValidType(A, 1);
5469   PetscValidType(B, 2);
5470   PetscValidBoolPointer(flg, 3);
5471   PetscCheckSameComm(A, 1, B, 2);
5472   MatCheckPreallocated(A, 1);
5473   MatCheckPreallocated(B, 2);
5474   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5476   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,
5477              B->cmap->N);
5478   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5479     PetscUseTypeMethod(A, equal, B, flg);
5480   } else {
5481     PetscCall(MatMultEqual(A, B, 10, flg));
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5488    matrices that are stored as vectors.  Either of the two scaling
5489    matrices can be `NULL`.
5490 
5491    Collective
5492 
5493    Input Parameters:
5494 +  mat - the matrix to be scaled
5495 .  l - the left scaling vector (or `NULL`)
5496 -  r - the right scaling vector (or `NULL`)
5497 
5498    Level: intermediate
5499 
5500    Note:
5501    `MatDiagonalScale()` computes A = LAR, where
5502    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5503    The L scales the rows of the matrix, the R scales the columns of the matrix.
5504 
5505 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5506 @*/
5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5511   PetscValidType(mat, 1);
5512   if (l) {
5513     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5514     PetscCheckSameComm(mat, 1, l, 2);
5515   }
5516   if (r) {
5517     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5518     PetscCheckSameComm(mat, 1, r, 3);
5519   }
5520   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5521   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5522   MatCheckPreallocated(mat, 1);
5523   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5524 
5525   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5526   PetscUseTypeMethod(mat, diagonalscale, l, r);
5527   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5528   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5529   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5530   PetscFunctionReturn(PETSC_SUCCESS);
5531 }
5532 
5533 /*@
5534     MatScale - Scales all elements of a matrix by a given number.
5535 
5536     Logically Collective
5537 
5538     Input Parameters:
5539 +   mat - the matrix to be scaled
5540 -   a  - the scaling value
5541 
5542     Level: intermediate
5543 
5544 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5545 @*/
5546 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5547 {
5548   PetscFunctionBegin;
5549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5550   PetscValidType(mat, 1);
5551   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5554   PetscValidLogicalCollectiveScalar(mat, a, 2);
5555   MatCheckPreallocated(mat, 1);
5556 
5557   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5558   if (a != (PetscScalar)1.0) {
5559     PetscUseTypeMethod(mat, scale, a);
5560     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5561   }
5562   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5563   PetscFunctionReturn(PETSC_SUCCESS);
5564 }
5565 
5566 /*@
5567    MatNorm - Calculates various norms of a matrix.
5568 
5569    Collective
5570 
5571    Input Parameters:
5572 +  mat - the matrix
5573 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5574 
5575    Output Parameter:
5576 .  nrm - the resulting norm
5577 
5578    Level: intermediate
5579 
5580 .seealso: [](chapter_matrices), `Mat`
5581 @*/
5582 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5583 {
5584   PetscFunctionBegin;
5585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5586   PetscValidType(mat, 1);
5587   PetscValidRealPointer(nrm, 3);
5588 
5589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5590   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5591   MatCheckPreallocated(mat, 1);
5592 
5593   PetscUseTypeMethod(mat, norm, type, nrm);
5594   PetscFunctionReturn(PETSC_SUCCESS);
5595 }
5596 
5597 /*
5598      This variable is used to prevent counting of MatAssemblyBegin() that
5599    are called from within a MatAssemblyEnd().
5600 */
5601 static PetscInt MatAssemblyEnd_InUse = 0;
5602 /*@
5603    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5604    be called after completing all calls to `MatSetValues()`.
5605 
5606    Collective
5607 
5608    Input Parameters:
5609 +  mat - the matrix
5610 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5611 
5612    Level: beginner
5613 
5614    Notes:
5615    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5616    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5617 
5618    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5619    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5620    using the matrix.
5621 
5622    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5623    same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is
5624    a global collective operation requiring all processes that share the matrix.
5625 
5626    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5627    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5628    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5629 
5630 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5631 @*/
5632 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5633 {
5634   PetscFunctionBegin;
5635   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5636   PetscValidType(mat, 1);
5637   MatCheckPreallocated(mat, 1);
5638   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5639   if (mat->assembled) {
5640     mat->was_assembled = PETSC_TRUE;
5641     mat->assembled     = PETSC_FALSE;
5642   }
5643 
5644   if (!MatAssemblyEnd_InUse) {
5645     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5646     PetscTryTypeMethod(mat, assemblybegin, type);
5647     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5648   } else PetscTryTypeMethod(mat, assemblybegin, type);
5649   PetscFunctionReturn(PETSC_SUCCESS);
5650 }
5651 
5652 /*@
5653    MatAssembled - Indicates if a matrix has been assembled and is ready for
5654      use; for example, in matrix-vector product.
5655 
5656    Not Collective
5657 
5658    Input Parameter:
5659 .  mat - the matrix
5660 
5661    Output Parameter:
5662 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5663 
5664    Level: advanced
5665 
5666 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5667 @*/
5668 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5669 {
5670   PetscFunctionBegin;
5671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5672   PetscValidBoolPointer(assembled, 2);
5673   *assembled = mat->assembled;
5674   PetscFunctionReturn(PETSC_SUCCESS);
5675 }
5676 
5677 /*@
5678    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5679    be called after `MatAssemblyBegin()`.
5680 
5681    Collective
5682 
5683    Input Parameters:
5684 +  mat - the matrix
5685 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5686 
5687    Options Database Keys:
5688 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5689 .  -mat_view ::ascii_info_detail - Prints more detailed info
5690 .  -mat_view - Prints matrix in ASCII format
5691 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5692 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5693 .  -display <name> - Sets display name (default is host)
5694 .  -draw_pause <sec> - Sets number of seconds to pause after display
5695 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5696 .  -viewer_socket_machine <machine> - Machine to use for socket
5697 .  -viewer_socket_port <port> - Port number to use for socket
5698 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5699 
5700    Level: beginner
5701 
5702 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5703 @*/
5704 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5705 {
5706   static PetscInt inassm = 0;
5707   PetscBool       flg    = PETSC_FALSE;
5708 
5709   PetscFunctionBegin;
5710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5711   PetscValidType(mat, 1);
5712 
5713   inassm++;
5714   MatAssemblyEnd_InUse++;
5715   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5716     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5717     PetscTryTypeMethod(mat, assemblyend, type);
5718     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5719   } else PetscTryTypeMethod(mat, assemblyend, type);
5720 
5721   /* Flush assembly is not a true assembly */
5722   if (type != MAT_FLUSH_ASSEMBLY) {
5723     if (mat->num_ass) {
5724       if (!mat->symmetry_eternal) {
5725         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5726         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5727       }
5728       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5729       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5730     }
5731     mat->num_ass++;
5732     mat->assembled        = PETSC_TRUE;
5733     mat->ass_nonzerostate = mat->nonzerostate;
5734   }
5735 
5736   mat->insertmode = NOT_SET_VALUES;
5737   MatAssemblyEnd_InUse--;
5738   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5739   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5740     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5741 
5742     if (mat->checksymmetryonassembly) {
5743       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5744       if (flg) {
5745         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5746       } else {
5747         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5748       }
5749     }
5750     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5751   }
5752   inassm--;
5753   PetscFunctionReturn(PETSC_SUCCESS);
5754 }
5755 
5756 /*@
5757    MatSetOption - Sets a parameter option for a matrix. Some options
5758    may be specific to certain storage formats.  Some options
5759    determine how values will be inserted (or added). Sorted,
5760    row-oriented input will generally assemble the fastest. The default
5761    is row-oriented.
5762 
5763    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5764 
5765    Input Parameters:
5766 +  mat - the matrix
5767 .  option - the option, one of those listed below (and possibly others),
5768 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5769 
5770   Options Describing Matrix Structure:
5771 +    `MAT_SPD` - symmetric positive definite
5772 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5773 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5774 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5775 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5776 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5777 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5778 
5779    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5780    do not need to be computed (usually at a high cost)
5781 
5782    Options For Use with `MatSetValues()`:
5783    Insert a logically dense subblock, which can be
5784 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5785 
5786    These options reflect the data you pass in with `MatSetValues()`; it has
5787    nothing to do with how the data is stored internally in the matrix
5788    data structure.
5789 
5790    When (re)assembling a matrix, we can restrict the input for
5791    efficiency/debugging purposes.  These options include
5792 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5793 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5794 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5795 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5796 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5797 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5798         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5799         performance for very large process counts.
5800 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5801         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5802         functions, instead sending only neighbor messages.
5803 
5804    Level: intermediate
5805 
5806    Notes:
5807    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5808 
5809    Some options are relevant only for particular matrix types and
5810    are thus ignored by others.  Other options are not supported by
5811    certain matrix types and will generate an error message if set.
5812 
5813    If using Fortran to compute a matrix, one may need to
5814    use the column-oriented option (or convert to the row-oriented
5815    format).
5816 
5817    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5818    that would generate a new entry in the nonzero structure is instead
5819    ignored.  Thus, if memory has not already been allocated for this particular
5820    data, then the insertion is ignored. For dense matrices, in which
5821    the entire array is allocated, no entries are ever ignored.
5822    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5823 
5824    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5825    that would generate a new entry in the nonzero structure instead produces
5826    an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5827 
5828    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5829    that would generate a new entry that has not been preallocated will
5830    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5831    only.) This is a useful flag when debugging matrix memory preallocation.
5832    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5833 
5834    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5835    other processors should be dropped, rather than stashed.
5836    This is useful if you know that the "owning" processor is also
5837    always generating the correct matrix entries, so that PETSc need
5838    not transfer duplicate entries generated on another processor.
5839 
5840    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5841    searches during matrix assembly. When this flag is set, the hash table
5842    is created during the first matrix assembly. This hash table is
5843    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5844    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5845    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5846    supported by `MATMPIBAIJ` format only.
5847 
5848    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5849    are kept in the nonzero structure
5850 
5851    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5852    a zero location in the matrix
5853 
5854    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5855 
5856    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5857         zero row routines and thus improves performance for very large process counts.
5858 
5859    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5860         part of the matrix (since they should match the upper triangular part).
5861 
5862    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5863                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5864                      with finite difference schemes with non-periodic boundary conditions.
5865 
5866    Developer Note:
5867    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5868    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5869    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5870    not changed.
5871 
5872 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5873 @*/
5874 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5875 {
5876   PetscFunctionBegin;
5877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5878   if (op > 0) {
5879     PetscValidLogicalCollectiveEnum(mat, op, 2);
5880     PetscValidLogicalCollectiveBool(mat, flg, 3);
5881   }
5882 
5883   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5884 
5885   switch (op) {
5886   case MAT_FORCE_DIAGONAL_ENTRIES:
5887     mat->force_diagonals = flg;
5888     PetscFunctionReturn(PETSC_SUCCESS);
5889   case MAT_NO_OFF_PROC_ENTRIES:
5890     mat->nooffprocentries = flg;
5891     PetscFunctionReturn(PETSC_SUCCESS);
5892   case MAT_SUBSET_OFF_PROC_ENTRIES:
5893     mat->assembly_subset = flg;
5894     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5895 #if !defined(PETSC_HAVE_MPIUNI)
5896       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5897 #endif
5898       mat->stash.first_assembly_done = PETSC_FALSE;
5899     }
5900     PetscFunctionReturn(PETSC_SUCCESS);
5901   case MAT_NO_OFF_PROC_ZERO_ROWS:
5902     mat->nooffproczerorows = flg;
5903     PetscFunctionReturn(PETSC_SUCCESS);
5904   case MAT_SPD:
5905     if (flg) {
5906       mat->spd                    = PETSC_BOOL3_TRUE;
5907       mat->symmetric              = PETSC_BOOL3_TRUE;
5908       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5909     } else {
5910       mat->spd = PETSC_BOOL3_FALSE;
5911     }
5912     break;
5913   case MAT_SYMMETRIC:
5914     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5915     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5916 #if !defined(PETSC_USE_COMPLEX)
5917     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5918 #endif
5919     break;
5920   case MAT_HERMITIAN:
5921     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5922     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5923 #if !defined(PETSC_USE_COMPLEX)
5924     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5925 #endif
5926     break;
5927   case MAT_STRUCTURALLY_SYMMETRIC:
5928     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5929     break;
5930   case MAT_SYMMETRY_ETERNAL:
5931     PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false");
5932     mat->symmetry_eternal = flg;
5933     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5934     break;
5935   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5936     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false");
5937     mat->structural_symmetry_eternal = flg;
5938     break;
5939   case MAT_SPD_ETERNAL:
5940     PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false");
5941     mat->spd_eternal = flg;
5942     if (flg) {
5943       mat->structural_symmetry_eternal = PETSC_TRUE;
5944       mat->symmetry_eternal            = PETSC_TRUE;
5945     }
5946     break;
5947   case MAT_STRUCTURE_ONLY:
5948     mat->structure_only = flg;
5949     break;
5950   case MAT_SORTED_FULL:
5951     mat->sortedfull = flg;
5952     break;
5953   default:
5954     break;
5955   }
5956   PetscTryTypeMethod(mat, setoption, op, flg);
5957   PetscFunctionReturn(PETSC_SUCCESS);
5958 }
5959 
5960 /*@
5961    MatGetOption - Gets a parameter option that has been set for a matrix.
5962 
5963    Logically Collective
5964 
5965    Input Parameters:
5966 +  mat - the matrix
5967 -  option - the option, this only responds to certain options, check the code for which ones
5968 
5969    Output Parameter:
5970 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5971 
5972    Level: intermediate
5973 
5974     Notes:
5975     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5976 
5977     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5978     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5979 
5980 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5981     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5982 @*/
5983 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5984 {
5985   PetscFunctionBegin;
5986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5987   PetscValidType(mat, 1);
5988 
5989   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5990   PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
5991 
5992   switch (op) {
5993   case MAT_NO_OFF_PROC_ENTRIES:
5994     *flg = mat->nooffprocentries;
5995     break;
5996   case MAT_NO_OFF_PROC_ZERO_ROWS:
5997     *flg = mat->nooffproczerorows;
5998     break;
5999   case MAT_SYMMETRIC:
6000     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6001     break;
6002   case MAT_HERMITIAN:
6003     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6004     break;
6005   case MAT_STRUCTURALLY_SYMMETRIC:
6006     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6007     break;
6008   case MAT_SPD:
6009     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6010     break;
6011   case MAT_SYMMETRY_ETERNAL:
6012     *flg = mat->symmetry_eternal;
6013     break;
6014   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6015     *flg = mat->symmetry_eternal;
6016     break;
6017   default:
6018     break;
6019   }
6020   PetscFunctionReturn(PETSC_SUCCESS);
6021 }
6022 
6023 /*@
6024    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6025    this routine retains the old nonzero structure.
6026 
6027    Logically Collective
6028 
6029    Input Parameters:
6030 .  mat - the matrix
6031 
6032    Level: intermediate
6033 
6034    Note:
6035     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
6036    See the Performance chapter of the users manual for information on preallocating matrices.
6037 
6038 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6039 @*/
6040 PetscErrorCode MatZeroEntries(Mat mat)
6041 {
6042   PetscFunctionBegin;
6043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6044   PetscValidType(mat, 1);
6045   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6046   PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled");
6047   MatCheckPreallocated(mat, 1);
6048 
6049   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6050   PetscUseTypeMethod(mat, zeroentries);
6051   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6052   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6053   PetscFunctionReturn(PETSC_SUCCESS);
6054 }
6055 
6056 /*@
6057    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6058    of a set of rows and columns of a matrix.
6059 
6060    Collective
6061 
6062    Input Parameters:
6063 +  mat - the matrix
6064 .  numRows - the number of rows/columns to zero
6065 .  rows - the global row indices
6066 .  diag - value put in the diagonal of the eliminated rows
6067 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6068 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6069 
6070    Level: intermediate
6071 
6072    Notes:
6073    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6074 
6075    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6076    The other entries of `b` will be adjusted by the known values of `x` times the corresponding matrix entries in the columns that are being eliminated
6077 
6078    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6079    Krylov method to take advantage of the known solution on the zeroed rows.
6080 
6081    For the parallel case, all processes that share the matrix (i.e.,
6082    those in the communicator used for matrix creation) MUST call this
6083    routine, regardless of whether any rows being zeroed are owned by
6084    them.
6085 
6086    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6087 
6088    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6089    list only rows local to itself).
6090 
6091    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6092 
6093 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6094           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6095 @*/
6096 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6097 {
6098   PetscFunctionBegin;
6099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6100   PetscValidType(mat, 1);
6101   if (numRows) PetscValidIntPointer(rows, 3);
6102   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6103   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6104   MatCheckPreallocated(mat, 1);
6105 
6106   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6107   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6108   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6109   PetscFunctionReturn(PETSC_SUCCESS);
6110 }
6111 
6112 /*@
6113    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6114    of a set of rows and columns of a matrix.
6115 
6116    Collective
6117 
6118    Input Parameters:
6119 +  mat - the matrix
6120 .  is - the rows to zero
6121 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6122 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6123 -  b - optional vector of right hand side, that will be adjusted by provided solution
6124 
6125    Level: intermediate
6126 
6127    Note:
6128    See `MatZeroRowsColumns()` for details on how this routine operates.
6129 
6130 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6131           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6132 @*/
6133 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6134 {
6135   PetscInt        numRows;
6136   const PetscInt *rows;
6137 
6138   PetscFunctionBegin;
6139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6140   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6141   PetscValidType(mat, 1);
6142   PetscValidType(is, 2);
6143   PetscCall(ISGetLocalSize(is, &numRows));
6144   PetscCall(ISGetIndices(is, &rows));
6145   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6146   PetscCall(ISRestoreIndices(is, &rows));
6147   PetscFunctionReturn(PETSC_SUCCESS);
6148 }
6149 
6150 /*@
6151    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6152    of a set of rows of a matrix.
6153 
6154    Collective
6155 
6156    Input Parameters:
6157 +  mat - the matrix
6158 .  numRows - the number of rows to zero
6159 .  rows - the global row indices
6160 .  diag - value put in the diagonal of the zeroed rows
6161 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6162 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6163 
6164    Level: intermediate
6165 
6166    Notes:
6167    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6168 
6169    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6170 
6171    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6172    Krylov method to take advantage of the known solution on the zeroed rows.
6173 
6174    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6175    from the matrix.
6176 
6177    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6178    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6179    formats this does not alter the nonzero structure.
6180 
6181    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6182    of the matrix is not changed the values are
6183    merely zeroed.
6184 
6185    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6186    formats can optionally remove the main diagonal entry from the
6187    nonzero structure as well, by passing 0.0 as the final argument).
6188 
6189    For the parallel case, all processes that share the matrix (i.e.,
6190    those in the communicator used for matrix creation) MUST call this
6191    routine, regardless of whether any rows being zeroed are owned by
6192    them.
6193 
6194    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6195    list only rows local to itself).
6196 
6197    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6198    owns that are to be zeroed. This saves a global synchronization in the implementation.
6199 
6200 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6201           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6202 @*/
6203 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6204 {
6205   PetscFunctionBegin;
6206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6207   PetscValidType(mat, 1);
6208   if (numRows) PetscValidIntPointer(rows, 3);
6209   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6210   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6211   MatCheckPreallocated(mat, 1);
6212 
6213   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6214   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6215   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6216   PetscFunctionReturn(PETSC_SUCCESS);
6217 }
6218 
6219 /*@
6220    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6221    of a set of rows of a matrix.
6222 
6223    Collective
6224 
6225    Input Parameters:
6226 +  mat - the matrix
6227 .  is - index set of rows to remove (if `NULL` then no row is removed)
6228 .  diag - value put in all diagonals of eliminated rows
6229 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6230 -  b - optional vector of right hand side, that will be adjusted by provided solution
6231 
6232    Level: intermediate
6233 
6234    Note:
6235    See `MatZeroRows()` for details on how this routine operates.
6236 
6237 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6238           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6239 @*/
6240 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6241 {
6242   PetscInt        numRows = 0;
6243   const PetscInt *rows    = NULL;
6244 
6245   PetscFunctionBegin;
6246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6247   PetscValidType(mat, 1);
6248   if (is) {
6249     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6250     PetscCall(ISGetLocalSize(is, &numRows));
6251     PetscCall(ISGetIndices(is, &rows));
6252   }
6253   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6254   if (is) PetscCall(ISRestoreIndices(is, &rows));
6255   PetscFunctionReturn(PETSC_SUCCESS);
6256 }
6257 
6258 /*@
6259    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6260    of a set of rows of a matrix. These rows must be local to the process.
6261 
6262    Collective
6263 
6264    Input Parameters:
6265 +  mat - the matrix
6266 .  numRows - the number of rows to remove
6267 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6268 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6269 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6270 -  b - optional vector of right hand side, that will be adjusted by provided solution
6271 
6272    Level: intermediate
6273 
6274    Notes:
6275    See `MatZeroRows()` for details on how this routine operates.
6276 
6277    The grid coordinates are across the entire grid, not just the local portion
6278 
6279    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6280    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6281    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6282    `DM_BOUNDARY_PERIODIC` boundary type.
6283 
6284    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6285    a single value per point) you can skip filling those indices.
6286 
6287    Fortran Note:
6288    `idxm` and `idxn` should be declared as
6289 $     MatStencil idxm(4,m)
6290    and the values inserted using
6291 .vb
6292     idxm(MatStencil_i,1) = i
6293     idxm(MatStencil_j,1) = j
6294     idxm(MatStencil_k,1) = k
6295     idxm(MatStencil_c,1) = c
6296    etc
6297 .ve
6298 
6299 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6300           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6301 @*/
6302 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6303 {
6304   PetscInt  dim    = mat->stencil.dim;
6305   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6306   PetscInt *dims   = mat->stencil.dims + 1;
6307   PetscInt *starts = mat->stencil.starts;
6308   PetscInt *dxm    = (PetscInt *)rows;
6309   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6310 
6311   PetscFunctionBegin;
6312   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6313   PetscValidType(mat, 1);
6314   if (numRows) PetscValidPointer(rows, 3);
6315 
6316   PetscCall(PetscMalloc1(numRows, &jdxm));
6317   for (i = 0; i < numRows; ++i) {
6318     /* Skip unused dimensions (they are ordered k, j, i, c) */
6319     for (j = 0; j < 3 - sdim; ++j) dxm++;
6320     /* Local index in X dir */
6321     tmp = *dxm++ - starts[0];
6322     /* Loop over remaining dimensions */
6323     for (j = 0; j < dim - 1; ++j) {
6324       /* If nonlocal, set index to be negative */
6325       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6326       /* Update local index */
6327       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6328     }
6329     /* Skip component slot if necessary */
6330     if (mat->stencil.noc) dxm++;
6331     /* Local row number */
6332     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6333   }
6334   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6335   PetscCall(PetscFree(jdxm));
6336   PetscFunctionReturn(PETSC_SUCCESS);
6337 }
6338 
6339 /*@
6340    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6341    of a set of rows and columns of a matrix.
6342 
6343    Collective
6344 
6345    Input Parameters:
6346 +  mat - the matrix
6347 .  numRows - the number of rows/columns to remove
6348 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6349 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6350 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6351 -  b - optional vector of right hand side, that will be adjusted by provided solution
6352 
6353    Level: intermediate
6354 
6355    Notes:
6356    See `MatZeroRowsColumns()` for details on how this routine operates.
6357 
6358    The grid coordinates are across the entire grid, not just the local portion
6359 
6360    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6361    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6362    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6363    `DM_BOUNDARY_PERIODIC` boundary type.
6364 
6365    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6366    a single value per point) you can skip filling those indices.
6367 
6368    Fortran Note:
6369    `idxm` and `idxn` should be declared as
6370 $     MatStencil idxm(4,m)
6371    and the values inserted using
6372 .vb
6373     idxm(MatStencil_i,1) = i
6374     idxm(MatStencil_j,1) = j
6375     idxm(MatStencil_k,1) = k
6376     idxm(MatStencil_c,1) = c
6377     etc
6378 .ve
6379 
6380 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6381           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6382 @*/
6383 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6384 {
6385   PetscInt  dim    = mat->stencil.dim;
6386   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6387   PetscInt *dims   = mat->stencil.dims + 1;
6388   PetscInt *starts = mat->stencil.starts;
6389   PetscInt *dxm    = (PetscInt *)rows;
6390   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6391 
6392   PetscFunctionBegin;
6393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6394   PetscValidType(mat, 1);
6395   if (numRows) PetscValidPointer(rows, 3);
6396 
6397   PetscCall(PetscMalloc1(numRows, &jdxm));
6398   for (i = 0; i < numRows; ++i) {
6399     /* Skip unused dimensions (they are ordered k, j, i, c) */
6400     for (j = 0; j < 3 - sdim; ++j) dxm++;
6401     /* Local index in X dir */
6402     tmp = *dxm++ - starts[0];
6403     /* Loop over remaining dimensions */
6404     for (j = 0; j < dim - 1; ++j) {
6405       /* If nonlocal, set index to be negative */
6406       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6407       /* Update local index */
6408       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6409     }
6410     /* Skip component slot if necessary */
6411     if (mat->stencil.noc) dxm++;
6412     /* Local row number */
6413     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6414   }
6415   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6416   PetscCall(PetscFree(jdxm));
6417   PetscFunctionReturn(PETSC_SUCCESS);
6418 }
6419 
6420 /*@C
6421    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6422    of a set of rows of a matrix; using local numbering of rows.
6423 
6424    Collective
6425 
6426    Input Parameters:
6427 +  mat - the matrix
6428 .  numRows - the number of rows to remove
6429 .  rows - the local row indices
6430 .  diag - value put in all diagonals of eliminated rows
6431 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6432 -  b - optional vector of right hand side, that will be adjusted by provided solution
6433 
6434    Level: intermediate
6435 
6436    Notes:
6437    Before calling `MatZeroRowsLocal()`, the user must first set the
6438    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6439 
6440    See `MatZeroRows()` for details on how this routine operates.
6441 
6442 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6443           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6444 @*/
6445 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6446 {
6447   PetscFunctionBegin;
6448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6449   PetscValidType(mat, 1);
6450   if (numRows) PetscValidIntPointer(rows, 3);
6451   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6452   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6453   MatCheckPreallocated(mat, 1);
6454 
6455   if (mat->ops->zerorowslocal) {
6456     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6457   } else {
6458     IS              is, newis;
6459     const PetscInt *newRows;
6460 
6461     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6462     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6463     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6464     PetscCall(ISGetIndices(newis, &newRows));
6465     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6466     PetscCall(ISRestoreIndices(newis, &newRows));
6467     PetscCall(ISDestroy(&newis));
6468     PetscCall(ISDestroy(&is));
6469   }
6470   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6471   PetscFunctionReturn(PETSC_SUCCESS);
6472 }
6473 
6474 /*@
6475    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6476    of a set of rows of a matrix; using local numbering of rows.
6477 
6478    Collective
6479 
6480    Input Parameters:
6481 +  mat - the matrix
6482 .  is - index set of rows to remove
6483 .  diag - value put in all diagonals of eliminated rows
6484 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6485 -  b - optional vector of right hand side, that will be adjusted by provided solution
6486 
6487    Level: intermediate
6488 
6489    Notes:
6490    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6491    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6492 
6493    See `MatZeroRows()` for details on how this routine operates.
6494 
6495 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6496           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6497 @*/
6498 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6499 {
6500   PetscInt        numRows;
6501   const PetscInt *rows;
6502 
6503   PetscFunctionBegin;
6504   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6505   PetscValidType(mat, 1);
6506   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6507   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6508   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6509   MatCheckPreallocated(mat, 1);
6510 
6511   PetscCall(ISGetLocalSize(is, &numRows));
6512   PetscCall(ISGetIndices(is, &rows));
6513   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6514   PetscCall(ISRestoreIndices(is, &rows));
6515   PetscFunctionReturn(PETSC_SUCCESS);
6516 }
6517 
6518 /*@
6519    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6520    of a set of rows and columns of a matrix; using local numbering of rows.
6521 
6522    Collective
6523 
6524    Input Parameters:
6525 +  mat - the matrix
6526 .  numRows - the number of rows to remove
6527 .  rows - the global row indices
6528 .  diag - value put in all diagonals of eliminated rows
6529 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6530 -  b - optional vector of right hand side, that will be adjusted by provided solution
6531 
6532    Level: intermediate
6533 
6534    Notes:
6535    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6536    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6537 
6538    See `MatZeroRowsColumns()` for details on how this routine operates.
6539 
6540 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6541           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6542 @*/
6543 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6544 {
6545   IS              is, newis;
6546   const PetscInt *newRows;
6547 
6548   PetscFunctionBegin;
6549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6550   PetscValidType(mat, 1);
6551   if (numRows) PetscValidIntPointer(rows, 3);
6552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6554   MatCheckPreallocated(mat, 1);
6555 
6556   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6557   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6558   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6559   PetscCall(ISGetIndices(newis, &newRows));
6560   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6561   PetscCall(ISRestoreIndices(newis, &newRows));
6562   PetscCall(ISDestroy(&newis));
6563   PetscCall(ISDestroy(&is));
6564   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6565   PetscFunctionReturn(PETSC_SUCCESS);
6566 }
6567 
6568 /*@
6569    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6570    of a set of rows and columns of a matrix; using local numbering of rows.
6571 
6572    Collective
6573 
6574    Input Parameters:
6575 +  mat - the matrix
6576 .  is - index set of rows to remove
6577 .  diag - value put in all diagonals of eliminated rows
6578 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6579 -  b - optional vector of right hand side, that will be adjusted by provided solution
6580 
6581    Level: intermediate
6582 
6583    Notes:
6584    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6585    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6586 
6587    See `MatZeroRowsColumns()` for details on how this routine operates.
6588 
6589 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6590           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6591 @*/
6592 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6593 {
6594   PetscInt        numRows;
6595   const PetscInt *rows;
6596 
6597   PetscFunctionBegin;
6598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6599   PetscValidType(mat, 1);
6600   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6601   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6602   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6603   MatCheckPreallocated(mat, 1);
6604 
6605   PetscCall(ISGetLocalSize(is, &numRows));
6606   PetscCall(ISGetIndices(is, &rows));
6607   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6608   PetscCall(ISRestoreIndices(is, &rows));
6609   PetscFunctionReturn(PETSC_SUCCESS);
6610 }
6611 
6612 /*@C
6613    MatGetSize - Returns the numbers of rows and columns in a matrix.
6614 
6615    Not Collective
6616 
6617    Input Parameter:
6618 .  mat - the matrix
6619 
6620    Level: beginner
6621 
6622    Output Parameters:
6623 +  m - the number of global rows
6624 -  n - the number of global columns
6625 
6626    Note:
6627    Both output parameters can be `NULL` on input.
6628 
6629 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6630 @*/
6631 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6632 {
6633   PetscFunctionBegin;
6634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6635   if (m) *m = mat->rmap->N;
6636   if (n) *n = mat->cmap->N;
6637   PetscFunctionReturn(PETSC_SUCCESS);
6638 }
6639 
6640 /*@C
6641    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6642    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6643 
6644    Not Collective
6645 
6646    Input Parameter:
6647 .  mat - the matrix
6648 
6649    Output Parameters:
6650 +  m - the number of local rows, use `NULL` to not obtain this value
6651 -  n - the number of local columns, use `NULL` to not obtain this value
6652 
6653    Level: beginner
6654 
6655 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6656 @*/
6657 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6658 {
6659   PetscFunctionBegin;
6660   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6661   if (m) PetscValidIntPointer(m, 2);
6662   if (n) PetscValidIntPointer(n, 3);
6663   if (m) *m = mat->rmap->n;
6664   if (n) *n = mat->cmap->n;
6665   PetscFunctionReturn(PETSC_SUCCESS);
6666 }
6667 
6668 /*@C
6669    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6670    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6671 
6672    Not Collective, unless matrix has not been allocated, then collective
6673 
6674    Input Parameter:
6675 .  mat - the matrix
6676 
6677    Output Parameters:
6678 +  m - the global index of the first local column, use `NULL` to not obtain this value
6679 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6680 
6681    Level: developer
6682 
6683 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6684 @*/
6685 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6686 {
6687   PetscFunctionBegin;
6688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6689   PetscValidType(mat, 1);
6690   if (m) PetscValidIntPointer(m, 2);
6691   if (n) PetscValidIntPointer(n, 3);
6692   MatCheckPreallocated(mat, 1);
6693   if (m) *m = mat->cmap->rstart;
6694   if (n) *n = mat->cmap->rend;
6695   PetscFunctionReturn(PETSC_SUCCESS);
6696 }
6697 
6698 /*@C
6699    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6700    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6701    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6702 
6703    Not Collective
6704 
6705    Input Parameter:
6706 .  mat - the matrix
6707 
6708    Output Parameters:
6709 +  m - the global index of the first local row, use `NULL` to not obtain this value
6710 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6711 
6712    Level: beginner
6713 
6714    Note:
6715   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6716   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6717   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6718 
6719 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6720           `PetscLayout`
6721 @*/
6722 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6723 {
6724   PetscFunctionBegin;
6725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6726   PetscValidType(mat, 1);
6727   if (m) PetscValidIntPointer(m, 2);
6728   if (n) PetscValidIntPointer(n, 3);
6729   MatCheckPreallocated(mat, 1);
6730   if (m) *m = mat->rmap->rstart;
6731   if (n) *n = mat->rmap->rend;
6732   PetscFunctionReturn(PETSC_SUCCESS);
6733 }
6734 
6735 /*@C
6736    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6737    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6738    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6739 
6740    Not Collective, unless matrix has not been allocated
6741 
6742    Input Parameters:
6743 .  mat - the matrix
6744 
6745    Output Parameter:
6746 .  ranges - start of each processors portion plus one more than the total length at the end
6747 
6748    Level: beginner
6749 
6750 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6751 @*/
6752 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6753 {
6754   PetscFunctionBegin;
6755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6756   PetscValidType(mat, 1);
6757   MatCheckPreallocated(mat, 1);
6758   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6759   PetscFunctionReturn(PETSC_SUCCESS);
6760 }
6761 
6762 /*@C
6763    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6764    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6765 
6766    Not Collective, unless matrix has not been allocated
6767 
6768    Input Parameters:
6769 .  mat - the matrix
6770 
6771    Output Parameter:
6772 .  ranges - start of each processors portion plus one more then the total length at the end
6773 
6774    Level: beginner
6775 
6776 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6777 @*/
6778 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6779 {
6780   PetscFunctionBegin;
6781   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6782   PetscValidType(mat, 1);
6783   MatCheckPreallocated(mat, 1);
6784   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6785   PetscFunctionReturn(PETSC_SUCCESS);
6786 }
6787 
6788 /*@C
6789    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6790    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6791    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6792 
6793    Not Collective
6794 
6795    Input Parameter:
6796 .  A - matrix
6797 
6798    Output Parameters:
6799 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6800 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6801 
6802    Level: intermediate
6803 
6804 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6805 @*/
6806 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6807 {
6808   PetscErrorCode (*f)(Mat, IS *, IS *);
6809 
6810   PetscFunctionBegin;
6811   MatCheckPreallocated(A, 1);
6812   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6813   if (f) {
6814     PetscCall((*f)(A, rows, cols));
6815   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6816     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6817     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6818   }
6819   PetscFunctionReturn(PETSC_SUCCESS);
6820 }
6821 
6822 /*@C
6823    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6824    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6825    to complete the factorization.
6826 
6827    Collective
6828 
6829    Input Parameters:
6830 +  fact - the factorized matrix obtained with `MatGetFactor()`
6831 .  mat - the matrix
6832 .  row - row permutation
6833 .  col - column permutation
6834 -  info - structure containing
6835 .vb
6836       levels - number of levels of fill.
6837       expected fill - as ratio of original fill.
6838       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6839                 missing diagonal entries)
6840 .ve
6841 
6842    Output Parameter:
6843 .  fact - new matrix that has been symbolically factored
6844 
6845    Level: developer
6846 
6847    Notes:
6848    See [Matrix Factorization](sec_matfactor) for additional information.
6849 
6850    Most users should employ the `KSP` interface for linear solvers
6851    instead of working directly with matrix algebra routines such as this.
6852    See, e.g., `KSPCreate()`.
6853 
6854    Uses the definition of level of fill as in Y. Saad, 2003
6855 
6856    Developer Note:
6857    The Fortran interface is not autogenerated as the
6858    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6859 
6860    References:
6861 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6862 
6863 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6864           `MatGetOrdering()`, `MatFactorInfo`
6865 @*/
6866 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6867 {
6868   PetscFunctionBegin;
6869   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6870   PetscValidType(mat, 2);
6871   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6872   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6873   PetscValidPointer(info, 5);
6874   PetscValidPointer(fact, 1);
6875   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6876   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6877   if (!fact->ops->ilufactorsymbolic) {
6878     MatSolverType stype;
6879     PetscCall(MatFactorGetSolverType(fact, &stype));
6880     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6881   }
6882   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6883   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6884   MatCheckPreallocated(mat, 2);
6885 
6886   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6887   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6888   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6889   PetscFunctionReturn(PETSC_SUCCESS);
6890 }
6891 
6892 /*@C
6893    MatICCFactorSymbolic - Performs symbolic incomplete
6894    Cholesky factorization for a symmetric matrix.  Use
6895    `MatCholeskyFactorNumeric()` to complete the factorization.
6896 
6897    Collective
6898 
6899    Input Parameters:
6900 +  fact - the factorized matrix obtained with `MatGetFactor()`
6901 .  mat - the matrix to be factored
6902 .  perm - row and column permutation
6903 -  info - structure containing
6904 .vb
6905       levels - number of levels of fill.
6906       expected fill - as ratio of original fill.
6907 .ve
6908 
6909    Level: developer
6910 
6911    Notes:
6912    Most users should employ the `KSP` interface for linear solvers
6913    instead of working directly with matrix algebra routines such as this.
6914    See, e.g., `KSPCreate()`.
6915 
6916    This uses the definition of level of fill as in Y. Saad, 2003
6917 
6918    Developer Note:
6919    The Fortran interface is not autogenerated as the
6920    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6921 
6922    References:
6923 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6924 
6925 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6926 @*/
6927 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6928 {
6929   PetscFunctionBegin;
6930   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6931   PetscValidType(mat, 2);
6932   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6933   PetscValidPointer(info, 4);
6934   PetscValidPointer(fact, 1);
6935   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6936   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6937   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6938   if (!(fact)->ops->iccfactorsymbolic) {
6939     MatSolverType stype;
6940     PetscCall(MatFactorGetSolverType(fact, &stype));
6941     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6942   }
6943   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6944   MatCheckPreallocated(mat, 2);
6945 
6946   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6947   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6948   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6949   PetscFunctionReturn(PETSC_SUCCESS);
6950 }
6951 
6952 /*@C
6953    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6954    points to an array of valid matrices, they may be reused to store the new
6955    submatrices.
6956 
6957    Collective
6958 
6959    Input Parameters:
6960 +  mat - the matrix
6961 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6962 .  irow - index set of rows to extract
6963 .  icol - index set of columns to extract
6964 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6965 
6966    Output Parameter:
6967 .  submat - the array of submatrices
6968 
6969    Level: advanced
6970 
6971    Notes:
6972    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6973    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6974    to extract a parallel submatrix.
6975 
6976    Some matrix types place restrictions on the row and column
6977    indices, such as that they be sorted or that they be equal to each other.
6978 
6979    The index sets may not have duplicate entries.
6980 
6981    When extracting submatrices from a parallel matrix, each processor can
6982    form a different submatrix by setting the rows and columns of its
6983    individual index sets according to the local submatrix desired.
6984 
6985    When finished using the submatrices, the user should destroy
6986    them with `MatDestroySubMatrices()`.
6987 
6988    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6989    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6990 
6991    This routine creates the matrices in submat; you should NOT create them before
6992    calling it. It also allocates the array of matrix pointers submat.
6993 
6994    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6995    request one row/column in a block, they must request all rows/columns that are in
6996    that block. For example, if the block size is 2 you cannot request just row 0 and
6997    column 0.
6998 
6999    Fortran Note:
7000    The Fortran interface is slightly different from that given below; it
7001    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7002 
7003 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7004 @*/
7005 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7006 {
7007   PetscInt  i;
7008   PetscBool eq;
7009 
7010   PetscFunctionBegin;
7011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7012   PetscValidType(mat, 1);
7013   if (n) {
7014     PetscValidPointer(irow, 3);
7015     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7016     PetscValidPointer(icol, 4);
7017     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7018   }
7019   PetscValidPointer(submat, 6);
7020   if (n && scall == MAT_REUSE_MATRIX) {
7021     PetscValidPointer(*submat, 6);
7022     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7023   }
7024   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7025   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7026   MatCheckPreallocated(mat, 1);
7027   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7028   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7029   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7030   for (i = 0; i < n; i++) {
7031     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7032     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7033     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7034 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7035     if (mat->boundtocpu && mat->bindingpropagates) {
7036       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7037       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7038     }
7039 #endif
7040   }
7041   PetscFunctionReturn(PETSC_SUCCESS);
7042 }
7043 
7044 /*@C
7045    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7046 
7047    Collective
7048 
7049    Input Parameters:
7050 +  mat - the matrix
7051 .  n   - the number of submatrixes to be extracted
7052 .  irow - index set of rows to extract
7053 .  icol - index set of columns to extract
7054 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7055 
7056    Output Parameter:
7057 .  submat - the array of submatrices
7058 
7059    Level: advanced
7060 
7061    Note:
7062    This is used by `PCGASM`
7063 
7064 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7065 @*/
7066 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7067 {
7068   PetscInt  i;
7069   PetscBool eq;
7070 
7071   PetscFunctionBegin;
7072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7073   PetscValidType(mat, 1);
7074   if (n) {
7075     PetscValidPointer(irow, 3);
7076     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7077     PetscValidPointer(icol, 4);
7078     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7079   }
7080   PetscValidPointer(submat, 6);
7081   if (n && scall == MAT_REUSE_MATRIX) {
7082     PetscValidPointer(*submat, 6);
7083     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7084   }
7085   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7086   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7087   MatCheckPreallocated(mat, 1);
7088 
7089   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7090   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7091   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7092   for (i = 0; i < n; i++) {
7093     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7094     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7095   }
7096   PetscFunctionReturn(PETSC_SUCCESS);
7097 }
7098 
7099 /*@C
7100    MatDestroyMatrices - Destroys an array of matrices.
7101 
7102    Collective
7103 
7104    Input Parameters:
7105 +  n - the number of local matrices
7106 -  mat - the matrices (this is a pointer to the array of matrices)
7107 
7108    Level: advanced
7109 
7110     Note:
7111     Frees not only the matrices, but also the array that contains the matrices
7112 
7113     Fortran Note:
7114     This does not free the array.
7115 
7116 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7117 @*/
7118 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7119 {
7120   PetscInt i;
7121 
7122   PetscFunctionBegin;
7123   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7124   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7125   PetscValidPointer(mat, 2);
7126 
7127   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7128 
7129   /* memory is allocated even if n = 0 */
7130   PetscCall(PetscFree(*mat));
7131   PetscFunctionReturn(PETSC_SUCCESS);
7132 }
7133 
7134 /*@C
7135    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7136 
7137    Collective
7138 
7139    Input Parameters:
7140 +  n - the number of local matrices
7141 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7142                        sequence of `MatCreateSubMatrices()`)
7143 
7144    Level: advanced
7145 
7146     Note:
7147     Frees not only the matrices, but also the array that contains the matrices
7148 
7149     Fortran Note:
7150     This does not free the array.
7151 
7152 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7153 @*/
7154 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7155 {
7156   Mat mat0;
7157 
7158   PetscFunctionBegin;
7159   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7160   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7161   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7162   PetscValidPointer(mat, 2);
7163 
7164   mat0 = (*mat)[0];
7165   if (mat0 && mat0->ops->destroysubmatrices) {
7166     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7167   } else {
7168     PetscCall(MatDestroyMatrices(n, mat));
7169   }
7170   PetscFunctionReturn(PETSC_SUCCESS);
7171 }
7172 
7173 /*@C
7174    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7175 
7176    Collective
7177 
7178    Input Parameters:
7179 .  mat - the matrix
7180 
7181    Output Parameter:
7182 .  matstruct - the sequential matrix with the nonzero structure of mat
7183 
7184   Level: developer
7185 
7186 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7187 @*/
7188 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7189 {
7190   PetscFunctionBegin;
7191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7192   PetscValidPointer(matstruct, 2);
7193 
7194   PetscValidType(mat, 1);
7195   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7196   MatCheckPreallocated(mat, 1);
7197 
7198   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7199   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7200   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7201   PetscFunctionReturn(PETSC_SUCCESS);
7202 }
7203 
7204 /*@C
7205    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7206 
7207    Collective
7208 
7209    Input Parameters:
7210 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7211                        sequence of `MatGetSequentialNonzeroStructure()`)
7212 
7213    Level: advanced
7214 
7215     Note:
7216     Frees not only the matrices, but also the array that contains the matrices
7217 
7218 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7219 @*/
7220 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7221 {
7222   PetscFunctionBegin;
7223   PetscValidPointer(mat, 1);
7224   PetscCall(MatDestroy(mat));
7225   PetscFunctionReturn(PETSC_SUCCESS);
7226 }
7227 
7228 /*@
7229    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7230    replaces the index sets by larger ones that represent submatrices with
7231    additional overlap.
7232 
7233    Collective
7234 
7235    Input Parameters:
7236 +  mat - the matrix
7237 .  n   - the number of index sets
7238 .  is  - the array of index sets (these index sets will changed during the call)
7239 -  ov  - the additional overlap requested
7240 
7241    Options Database Key:
7242 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7243 
7244    Level: developer
7245 
7246    Note:
7247    The computed overlap preserves the matrix block sizes when the blocks are square.
7248    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7249    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7250 
7251 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7252 @*/
7253 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7254 {
7255   PetscInt i, bs, cbs;
7256 
7257   PetscFunctionBegin;
7258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7259   PetscValidType(mat, 1);
7260   PetscValidLogicalCollectiveInt(mat, n, 2);
7261   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7262   if (n) {
7263     PetscValidPointer(is, 3);
7264     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7265   }
7266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7268   MatCheckPreallocated(mat, 1);
7269 
7270   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7271   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7272   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7273   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7274   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7275   if (bs == cbs) {
7276     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7277   }
7278   PetscFunctionReturn(PETSC_SUCCESS);
7279 }
7280 
7281 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7282 
7283 /*@
7284    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7285    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7286    additional overlap.
7287 
7288    Collective
7289 
7290    Input Parameters:
7291 +  mat - the matrix
7292 .  n   - the number of index sets
7293 .  is  - the array of index sets (these index sets will changed during the call)
7294 -  ov  - the additional overlap requested
7295 
7296 `   Options Database Key:
7297 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7298 
7299    Level: developer
7300 
7301 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7302 @*/
7303 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7304 {
7305   PetscInt i;
7306 
7307   PetscFunctionBegin;
7308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7309   PetscValidType(mat, 1);
7310   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7311   if (n) {
7312     PetscValidPointer(is, 3);
7313     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7314   }
7315   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7316   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7317   MatCheckPreallocated(mat, 1);
7318   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7319   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7320   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7321   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7322   PetscFunctionReturn(PETSC_SUCCESS);
7323 }
7324 
7325 /*@
7326    MatGetBlockSize - Returns the matrix block size.
7327 
7328    Not Collective
7329 
7330    Input Parameter:
7331 .  mat - the matrix
7332 
7333    Output Parameter:
7334 .  bs - block size
7335 
7336    Level: intermediate
7337 
7338    Notes:
7339     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7340 
7341    If the block size has not been set yet this routine returns 1.
7342 
7343 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7344 @*/
7345 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7346 {
7347   PetscFunctionBegin;
7348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7349   PetscValidIntPointer(bs, 2);
7350   *bs = PetscAbs(mat->rmap->bs);
7351   PetscFunctionReturn(PETSC_SUCCESS);
7352 }
7353 
7354 /*@
7355    MatGetBlockSizes - Returns the matrix block row and column sizes.
7356 
7357    Not Collective
7358 
7359    Input Parameter:
7360 .  mat - the matrix
7361 
7362    Output Parameters:
7363 +  rbs - row block size
7364 -  cbs - column block size
7365 
7366    Level: intermediate
7367 
7368    Notes:
7369     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7370     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7371 
7372    If a block size has not been set yet this routine returns 1.
7373 
7374 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7375 @*/
7376 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7377 {
7378   PetscFunctionBegin;
7379   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7380   if (rbs) PetscValidIntPointer(rbs, 2);
7381   if (cbs) PetscValidIntPointer(cbs, 3);
7382   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7383   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7384   PetscFunctionReturn(PETSC_SUCCESS);
7385 }
7386 
7387 /*@
7388    MatSetBlockSize - Sets the matrix block size.
7389 
7390    Logically Collective
7391 
7392    Input Parameters:
7393 +  mat - the matrix
7394 -  bs - block size
7395 
7396    Level: intermediate
7397 
7398    Notes:
7399     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7400     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7401 
7402     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7403     is compatible with the matrix local sizes.
7404 
7405 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7406 @*/
7407 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7408 {
7409   PetscFunctionBegin;
7410   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7411   PetscValidLogicalCollectiveInt(mat, bs, 2);
7412   PetscCall(MatSetBlockSizes(mat, bs, bs));
7413   PetscFunctionReturn(PETSC_SUCCESS);
7414 }
7415 
7416 typedef struct {
7417   PetscInt         n;
7418   IS              *is;
7419   Mat             *mat;
7420   PetscObjectState nonzerostate;
7421   Mat              C;
7422 } EnvelopeData;
7423 
7424 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7425 {
7426   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7427   PetscCall(PetscFree(edata->is));
7428   PetscCall(PetscFree(edata));
7429   return PETSC_SUCCESS;
7430 }
7431 
7432 /*
7433    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7434          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7435 
7436    Collective
7437 
7438    Input Parameter:
7439 .  mat - the matrix
7440 
7441    Notes:
7442      There can be zeros within the blocks
7443 
7444      The blocks can overlap between processes, including laying on more than two processes
7445 
7446 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7447 */
7448 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7449 {
7450   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7451   PetscInt          *diag, *odiag, sc;
7452   VecScatter         scatter;
7453   PetscScalar       *seqv;
7454   const PetscScalar *parv;
7455   const PetscInt    *ia, *ja;
7456   PetscBool          set, flag, done;
7457   Mat                AA = mat, A;
7458   MPI_Comm           comm;
7459   PetscMPIInt        rank, size, tag;
7460   MPI_Status         status;
7461   PetscContainer     container;
7462   EnvelopeData      *edata;
7463   Vec                seq, par;
7464   IS                 isglobal;
7465 
7466   PetscFunctionBegin;
7467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7468   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7469   if (!set || !flag) {
7470     /* TOO: only needs nonzero structure of transpose */
7471     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7472     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7473   }
7474   PetscCall(MatAIJGetLocalMat(AA, &A));
7475   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7476   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7477 
7478   PetscCall(MatGetLocalSize(mat, &n, NULL));
7479   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7480   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7481   PetscCallMPI(MPI_Comm_size(comm, &size));
7482   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7483 
7484   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7485 
7486   if (rank > 0) {
7487     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7488     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7489   }
7490   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7491   for (i = 0; i < n; i++) {
7492     env = PetscMax(env, ja[ia[i + 1] - 1]);
7493     II  = rstart + i;
7494     if (env == II) {
7495       starts[lblocks]  = tbs;
7496       sizes[lblocks++] = 1 + II - tbs;
7497       tbs              = 1 + II;
7498     }
7499   }
7500   if (rank < size - 1) {
7501     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7502     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7503   }
7504 
7505   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7506   if (!set || !flag) PetscCall(MatDestroy(&AA));
7507   PetscCall(MatDestroy(&A));
7508 
7509   PetscCall(PetscNew(&edata));
7510   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7511   edata->n = lblocks;
7512   /* create IS needed for extracting blocks from the original matrix */
7513   PetscCall(PetscMalloc1(lblocks, &edata->is));
7514   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7515 
7516   /* Create the resulting inverse matrix structure with preallocation information */
7517   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7518   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7519   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7520   PetscCall(MatSetType(edata->C, MATAIJ));
7521 
7522   /* Communicate the start and end of each row, from each block to the correct rank */
7523   /* TODO: Use PetscSF instead of VecScatter */
7524   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7525   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7526   PetscCall(VecGetArrayWrite(seq, &seqv));
7527   for (PetscInt i = 0; i < lblocks; i++) {
7528     for (PetscInt j = 0; j < sizes[i]; j++) {
7529       seqv[cnt]     = starts[i];
7530       seqv[cnt + 1] = starts[i] + sizes[i];
7531       cnt += 2;
7532     }
7533   }
7534   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7535   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7536   sc -= cnt;
7537   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7538   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7539   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7540   PetscCall(ISDestroy(&isglobal));
7541   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7542   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7543   PetscCall(VecScatterDestroy(&scatter));
7544   PetscCall(VecDestroy(&seq));
7545   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7546   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7547   PetscCall(VecGetArrayRead(par, &parv));
7548   cnt = 0;
7549   PetscCall(MatGetSize(mat, NULL, &n));
7550   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7551     PetscInt start, end, d = 0, od = 0;
7552 
7553     start = (PetscInt)PetscRealPart(parv[cnt]);
7554     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7555     cnt += 2;
7556 
7557     if (start < cstart) {
7558       od += cstart - start + n - cend;
7559       d += cend - cstart;
7560     } else if (start < cend) {
7561       od += n - cend;
7562       d += cend - start;
7563     } else od += n - start;
7564     if (end <= cstart) {
7565       od -= cstart - end + n - cend;
7566       d -= cend - cstart;
7567     } else if (end < cend) {
7568       od -= n - cend;
7569       d -= cend - end;
7570     } else od -= n - end;
7571 
7572     odiag[i] = od;
7573     diag[i]  = d;
7574   }
7575   PetscCall(VecRestoreArrayRead(par, &parv));
7576   PetscCall(VecDestroy(&par));
7577   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7578   PetscCall(PetscFree2(diag, odiag));
7579   PetscCall(PetscFree2(sizes, starts));
7580 
7581   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7582   PetscCall(PetscContainerSetPointer(container, edata));
7583   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7584   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7585   PetscCall(PetscObjectDereference((PetscObject)container));
7586   PetscFunctionReturn(PETSC_SUCCESS);
7587 }
7588 
7589 /*@
7590   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7591 
7592   Collective
7593 
7594   Input Parameters:
7595 + A - the matrix
7596 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7597 
7598   Output Parameter:
7599 . C - matrix with inverted block diagonal of `A`
7600 
7601   Level: advanced
7602 
7603   Note:
7604      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7605 
7606 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7607 @*/
7608 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7609 {
7610   PetscContainer   container;
7611   EnvelopeData    *edata;
7612   PetscObjectState nonzerostate;
7613 
7614   PetscFunctionBegin;
7615   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7616   if (!container) {
7617     PetscCall(MatComputeVariableBlockEnvelope(A));
7618     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7619   }
7620   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7621   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7622   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7623   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7624 
7625   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7626   *C = edata->C;
7627 
7628   for (PetscInt i = 0; i < edata->n; i++) {
7629     Mat          D;
7630     PetscScalar *dvalues;
7631 
7632     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7633     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7634     PetscCall(MatSeqDenseInvert(D));
7635     PetscCall(MatDenseGetArray(D, &dvalues));
7636     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7637     PetscCall(MatDestroy(&D));
7638   }
7639   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7640   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7641   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7642   PetscFunctionReturn(PETSC_SUCCESS);
7643 }
7644 
7645 /*@
7646    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7647 
7648    Logically Collective
7649 
7650    Input Parameters:
7651 +  mat - the matrix
7652 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7653 -  bsizes - the block sizes
7654 
7655    Level: intermediate
7656 
7657    Notes:
7658     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7659 
7660     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.
7661 
7662 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7663           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7664 @*/
7665 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7666 {
7667   PetscInt i, ncnt = 0, nlocal;
7668 
7669   PetscFunctionBegin;
7670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7671   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7672   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7673   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7674   PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal);
7675   PetscCall(PetscFree(mat->bsizes));
7676   mat->nblocks = nblocks;
7677   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7678   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7679   PetscFunctionReturn(PETSC_SUCCESS);
7680 }
7681 
7682 /*@C
7683    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7684 
7685    Logically Collective; No Fortran Support
7686 
7687    Input Parameter:
7688 .  mat - the matrix
7689 
7690    Output Parameters:
7691 +  nblocks - the number of blocks on this process
7692 -  bsizes - the block sizes
7693 
7694    Level: intermediate
7695 
7696 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7697 @*/
7698 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7699 {
7700   PetscFunctionBegin;
7701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7702   *nblocks = mat->nblocks;
7703   *bsizes  = mat->bsizes;
7704   PetscFunctionReturn(PETSC_SUCCESS);
7705 }
7706 
7707 /*@
7708    MatSetBlockSizes - Sets the matrix block row and column sizes.
7709 
7710    Logically Collective
7711 
7712    Input Parameters:
7713 +  mat - the matrix
7714 .  rbs - row block size
7715 -  cbs - column block size
7716 
7717    Level: intermediate
7718 
7719    Notes:
7720     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7721     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7722     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7723 
7724     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7725     are compatible with the matrix local sizes.
7726 
7727     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7728 
7729 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7730 @*/
7731 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7732 {
7733   PetscFunctionBegin;
7734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7735   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7736   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7737   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7738   if (mat->rmap->refcnt) {
7739     ISLocalToGlobalMapping l2g  = NULL;
7740     PetscLayout            nmap = NULL;
7741 
7742     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7743     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7744     PetscCall(PetscLayoutDestroy(&mat->rmap));
7745     mat->rmap          = nmap;
7746     mat->rmap->mapping = l2g;
7747   }
7748   if (mat->cmap->refcnt) {
7749     ISLocalToGlobalMapping l2g  = NULL;
7750     PetscLayout            nmap = NULL;
7751 
7752     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7753     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7754     PetscCall(PetscLayoutDestroy(&mat->cmap));
7755     mat->cmap          = nmap;
7756     mat->cmap->mapping = l2g;
7757   }
7758   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7759   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7760   PetscFunctionReturn(PETSC_SUCCESS);
7761 }
7762 
7763 /*@
7764    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7765 
7766    Logically Collective
7767 
7768    Input Parameters:
7769 +  mat - the matrix
7770 .  fromRow - matrix from which to copy row block size
7771 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7772 
7773    Level: developer
7774 
7775 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7776 @*/
7777 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7778 {
7779   PetscFunctionBegin;
7780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7781   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7782   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7783   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7784   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7785   PetscFunctionReturn(PETSC_SUCCESS);
7786 }
7787 
7788 /*@
7789    MatResidual - Default routine to calculate the residual r = b - Ax
7790 
7791    Collective
7792 
7793    Input Parameters:
7794 +  mat - the matrix
7795 .  b   - the right-hand-side
7796 -  x   - the approximate solution
7797 
7798    Output Parameter:
7799 .  r - location to store the residual
7800 
7801    Level: developer
7802 
7803 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7804 @*/
7805 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7806 {
7807   PetscFunctionBegin;
7808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7809   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7810   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7811   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7812   PetscValidType(mat, 1);
7813   MatCheckPreallocated(mat, 1);
7814   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7815   if (!mat->ops->residual) {
7816     PetscCall(MatMult(mat, x, r));
7817     PetscCall(VecAYPX(r, -1.0, b));
7818   } else {
7819     PetscUseTypeMethod(mat, residual, b, x, r);
7820   }
7821   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7822   PetscFunctionReturn(PETSC_SUCCESS);
7823 }
7824 
7825 /*MC
7826     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7827 
7828     Synopsis:
7829     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7830 
7831     Not Collective
7832 
7833     Input Parameters:
7834 +   A - the matrix
7835 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7836 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7837 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7838                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7839                  always used.
7840 
7841     Output Parameters:
7842 +   n - number of local rows in the (possibly compressed) matrix
7843 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7844 .   ja - the column indices
7845 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7846            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7847 
7848     Level: developer
7849 
7850     Note:
7851     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7852 
7853 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7854 M*/
7855 
7856 /*MC
7857     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7858 
7859     Synopsis:
7860     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7861 
7862     Not Collective
7863 
7864     Input Parameters:
7865 +   A - the  matrix
7866 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7867 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7868     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7869                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7870                  always used.
7871 .   n - number of local rows in the (possibly compressed) matrix
7872 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7873 .   ja - the column indices
7874 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7875            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7876 
7877     Level: developer
7878 
7879 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7880 M*/
7881 
7882 /*@C
7883     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7884 
7885    Collective
7886 
7887     Input Parameters:
7888 +   mat - the matrix
7889 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7890 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7891 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7892                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7893                  always used.
7894 
7895     Output Parameters:
7896 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7897 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use `NULL` if not needed
7898 .   ja - the column indices, use `NULL` if not needed
7899 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7900            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7901 
7902     Level: developer
7903 
7904     Notes:
7905     You CANNOT change any of the ia[] or ja[] values.
7906 
7907     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7908 
7909     Fortran Notes:
7910     Use
7911 .vb
7912     PetscInt, pointer :: ia(:),ja(:)
7913     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7914     ! Access the ith and jth entries via ia(i) and ja(j)
7915 .ve
7916    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7917 
7918 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7919 @*/
7920 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7921 {
7922   PetscFunctionBegin;
7923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7924   PetscValidType(mat, 1);
7925   if (n) PetscValidIntPointer(n, 5);
7926   if (ia) PetscValidPointer(ia, 6);
7927   if (ja) PetscValidPointer(ja, 7);
7928   if (done) PetscValidBoolPointer(done, 8);
7929   MatCheckPreallocated(mat, 1);
7930   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7931   else {
7932     if (done) *done = PETSC_TRUE;
7933     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7934     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7935     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7936   }
7937   PetscFunctionReturn(PETSC_SUCCESS);
7938 }
7939 
7940 /*@C
7941     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7942 
7943     Collective
7944 
7945     Input Parameters:
7946 +   mat - the matrix
7947 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7948 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7949                 symmetrized
7950 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7951                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7952                  always used.
7953 .   n - number of columns in the (possibly compressed) matrix
7954 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7955 -   ja - the row indices
7956 
7957     Output Parameter:
7958 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7959 
7960     Level: developer
7961 
7962 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7963 @*/
7964 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7965 {
7966   PetscFunctionBegin;
7967   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7968   PetscValidType(mat, 1);
7969   PetscValidIntPointer(n, 5);
7970   if (ia) PetscValidPointer(ia, 6);
7971   if (ja) PetscValidPointer(ja, 7);
7972   PetscValidBoolPointer(done, 8);
7973   MatCheckPreallocated(mat, 1);
7974   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7975   else {
7976     *done = PETSC_TRUE;
7977     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7978   }
7979   PetscFunctionReturn(PETSC_SUCCESS);
7980 }
7981 
7982 /*@C
7983     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7984 
7985     Collective
7986 
7987     Input Parameters:
7988 +   mat - the matrix
7989 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7990 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7991 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7992                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7993                  always used.
7994 .   n - size of (possibly compressed) matrix
7995 .   ia - the row pointers
7996 -   ja - the column indices
7997 
7998     Output Parameter:
7999 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8000 
8001     Level: developer
8002 
8003     Note:
8004     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8005     us of the array after it has been restored. If you pass `NULL`, it will
8006     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8007 
8008     Fortran Note:
8009    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8010 
8011 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8012 @*/
8013 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8014 {
8015   PetscFunctionBegin;
8016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8017   PetscValidType(mat, 1);
8018   if (ia) PetscValidPointer(ia, 6);
8019   if (ja) PetscValidPointer(ja, 7);
8020   if (done) PetscValidBoolPointer(done, 8);
8021   MatCheckPreallocated(mat, 1);
8022 
8023   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8024   else {
8025     if (done) *done = PETSC_TRUE;
8026     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8027     if (n) *n = 0;
8028     if (ia) *ia = NULL;
8029     if (ja) *ja = NULL;
8030   }
8031   PetscFunctionReturn(PETSC_SUCCESS);
8032 }
8033 
8034 /*@C
8035     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8036 
8037     Collective
8038 
8039     Input Parameters:
8040 +   mat - the matrix
8041 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8042 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8043 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8044                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8045                  always used.
8046 
8047     Output Parameters:
8048 +   n - size of (possibly compressed) matrix
8049 .   ia - the column pointers
8050 .   ja - the row indices
8051 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8052 
8053     Level: developer
8054 
8055 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8056 @*/
8057 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8058 {
8059   PetscFunctionBegin;
8060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8061   PetscValidType(mat, 1);
8062   if (ia) PetscValidPointer(ia, 6);
8063   if (ja) PetscValidPointer(ja, 7);
8064   PetscValidBoolPointer(done, 8);
8065   MatCheckPreallocated(mat, 1);
8066 
8067   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8068   else {
8069     *done = PETSC_TRUE;
8070     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8071     if (n) *n = 0;
8072     if (ia) *ia = NULL;
8073     if (ja) *ja = NULL;
8074   }
8075   PetscFunctionReturn(PETSC_SUCCESS);
8076 }
8077 
8078 /*@C
8079     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8080 
8081     Collective
8082 
8083     Input Parameters:
8084 +   mat - the matrix
8085 .   ncolors - maximum color value
8086 .   n   - number of entries in colorarray
8087 -   colorarray - array indicating color for each column
8088 
8089     Output Parameter:
8090 .   iscoloring - coloring generated using colorarray information
8091 
8092     Level: developer
8093 
8094 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8095 @*/
8096 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8097 {
8098   PetscFunctionBegin;
8099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8100   PetscValidType(mat, 1);
8101   PetscValidIntPointer(colorarray, 4);
8102   PetscValidPointer(iscoloring, 5);
8103   MatCheckPreallocated(mat, 1);
8104 
8105   if (!mat->ops->coloringpatch) {
8106     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8107   } else {
8108     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8109   }
8110   PetscFunctionReturn(PETSC_SUCCESS);
8111 }
8112 
8113 /*@
8114    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8115 
8116    Logically Collective
8117 
8118    Input Parameter:
8119 .  mat - the factored matrix to be reset
8120 
8121    Level: developer
8122 
8123    Notes:
8124    This routine should be used only with factored matrices formed by in-place
8125    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8126    format).  This option can save memory, for example, when solving nonlinear
8127    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8128    ILU(0) preconditioner.
8129 
8130    One can specify in-place ILU(0) factorization by calling
8131 .vb
8132      PCType(pc,PCILU);
8133      PCFactorSeUseInPlace(pc);
8134 .ve
8135    or by using the options -pc_type ilu -pc_factor_in_place
8136 
8137    In-place factorization ILU(0) can also be used as a local
8138    solver for the blocks within the block Jacobi or additive Schwarz
8139    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8140    for details on setting local solver options.
8141 
8142    Most users should employ the `KSP` interface for linear solvers
8143    instead of working directly with matrix algebra routines such as this.
8144    See, e.g., `KSPCreate()`.
8145 
8146 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8147 @*/
8148 PetscErrorCode MatSetUnfactored(Mat mat)
8149 {
8150   PetscFunctionBegin;
8151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8152   PetscValidType(mat, 1);
8153   MatCheckPreallocated(mat, 1);
8154   mat->factortype = MAT_FACTOR_NONE;
8155   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8156   PetscUseTypeMethod(mat, setunfactored);
8157   PetscFunctionReturn(PETSC_SUCCESS);
8158 }
8159 
8160 /*MC
8161     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8162 
8163     Synopsis:
8164     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8165 
8166     Not Collective
8167 
8168     Input Parameter:
8169 .   x - matrix
8170 
8171     Output Parameters:
8172 +   xx_v - the Fortran pointer to the array
8173 -   ierr - error code
8174 
8175     Example of Usage:
8176 .vb
8177       PetscScalar, pointer xx_v(:,:)
8178       ....
8179       call MatDenseGetArrayF90(x,xx_v,ierr)
8180       a = xx_v(3)
8181       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8182 .ve
8183 
8184     Level: advanced
8185 
8186 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8187 M*/
8188 
8189 /*MC
8190     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8191     accessed with `MatDenseGetArrayF90()`.
8192 
8193     Synopsis:
8194     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8195 
8196     Not Collective
8197 
8198     Input Parameters:
8199 +   x - matrix
8200 -   xx_v - the Fortran90 pointer to the array
8201 
8202     Output Parameter:
8203 .   ierr - error code
8204 
8205     Example of Usage:
8206 .vb
8207        PetscScalar, pointer xx_v(:,:)
8208        ....
8209        call MatDenseGetArrayF90(x,xx_v,ierr)
8210        a = xx_v(3)
8211        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8212 .ve
8213 
8214     Level: advanced
8215 
8216 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8217 M*/
8218 
8219 /*MC
8220     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8221 
8222     Synopsis:
8223     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8224 
8225     Not Collective
8226 
8227     Input Parameter:
8228 .   x - matrix
8229 
8230     Output Parameters:
8231 +   xx_v - the Fortran pointer to the array
8232 -   ierr - error code
8233 
8234     Example of Usage:
8235 .vb
8236       PetscScalar, pointer xx_v(:)
8237       ....
8238       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8239       a = xx_v(3)
8240       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8241 .ve
8242 
8243     Level: advanced
8244 
8245 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8246 M*/
8247 
8248 /*MC
8249     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8250     accessed with `MatSeqAIJGetArrayF90()`.
8251 
8252     Synopsis:
8253     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8254 
8255     Not Collective
8256 
8257     Input Parameters:
8258 +   x - matrix
8259 -   xx_v - the Fortran90 pointer to the array
8260 
8261     Output Parameter:
8262 .   ierr - error code
8263 
8264     Example of Usage:
8265 .vb
8266        PetscScalar, pointer xx_v(:)
8267        ....
8268        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8269        a = xx_v(3)
8270        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8271 .ve
8272 
8273     Level: advanced
8274 
8275 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8276 M*/
8277 
8278 /*@
8279     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8280                       as the original matrix.
8281 
8282     Collective
8283 
8284     Input Parameters:
8285 +   mat - the original matrix
8286 .   isrow - parallel `IS` containing the rows this processor should obtain
8287 .   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.
8288 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8289 
8290     Output Parameter:
8291 .   newmat - the new submatrix, of the same type as the original matrix
8292 
8293     Level: advanced
8294 
8295     Notes:
8296     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8297 
8298     Some matrix types place restrictions on the row and column indices, such
8299     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;
8300     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8301 
8302     The index sets may not have duplicate entries.
8303 
8304       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8305    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8306    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8307    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8308    you are finished using it.
8309 
8310     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8311     the input matrix.
8312 
8313     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8314 
8315    Example usage:
8316    Consider the following 8x8 matrix with 34 non-zero values, that is
8317    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8318    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8319    as follows
8320 .vb
8321             1  2  0  |  0  3  0  |  0  4
8322     Proc0   0  5  6  |  7  0  0  |  8  0
8323             9  0 10  | 11  0  0  | 12  0
8324     -------------------------------------
8325            13  0 14  | 15 16 17  |  0  0
8326     Proc1   0 18  0  | 19 20 21  |  0  0
8327             0  0  0  | 22 23  0  | 24  0
8328     -------------------------------------
8329     Proc2  25 26 27  |  0  0 28  | 29  0
8330            30  0  0  | 31 32 33  |  0 34
8331 .ve
8332 
8333     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8334 
8335 .vb
8336             2  0  |  0  3  0  |  0
8337     Proc0   5  6  |  7  0  0  |  8
8338     -------------------------------
8339     Proc1  18  0  | 19 20 21  |  0
8340     -------------------------------
8341     Proc2  26 27  |  0  0 28  | 29
8342             0  0  | 31 32 33  |  0
8343 .ve
8344 
8345 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8346 @*/
8347 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8348 {
8349   PetscMPIInt size;
8350   Mat        *local;
8351   IS          iscoltmp;
8352   PetscBool   flg;
8353 
8354   PetscFunctionBegin;
8355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8356   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8357   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8358   PetscValidPointer(newmat, 5);
8359   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8360   PetscValidType(mat, 1);
8361   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8362   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8363 
8364   MatCheckPreallocated(mat, 1);
8365   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8366 
8367   if (!iscol || isrow == iscol) {
8368     PetscBool   stride;
8369     PetscMPIInt grabentirematrix = 0, grab;
8370     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8371     if (stride) {
8372       PetscInt first, step, n, rstart, rend;
8373       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8374       if (step == 1) {
8375         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8376         if (rstart == first) {
8377           PetscCall(ISGetLocalSize(isrow, &n));
8378           if (n == rend - rstart) grabentirematrix = 1;
8379         }
8380       }
8381     }
8382     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8383     if (grab) {
8384       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8385       if (cll == MAT_INITIAL_MATRIX) {
8386         *newmat = mat;
8387         PetscCall(PetscObjectReference((PetscObject)mat));
8388       }
8389       PetscFunctionReturn(PETSC_SUCCESS);
8390     }
8391   }
8392 
8393   if (!iscol) {
8394     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8395   } else {
8396     iscoltmp = iscol;
8397   }
8398 
8399   /* if original matrix is on just one processor then use submatrix generated */
8400   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8401     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8402     goto setproperties;
8403   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8404     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8405     *newmat = *local;
8406     PetscCall(PetscFree(local));
8407     goto setproperties;
8408   } else if (!mat->ops->createsubmatrix) {
8409     /* Create a new matrix type that implements the operation using the full matrix */
8410     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8411     switch (cll) {
8412     case MAT_INITIAL_MATRIX:
8413       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8414       break;
8415     case MAT_REUSE_MATRIX:
8416       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8417       break;
8418     default:
8419       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8420     }
8421     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8422     goto setproperties;
8423   }
8424 
8425   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8426   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8427   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8428 
8429 setproperties:
8430   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8431   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8432   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8433   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8434   PetscFunctionReturn(PETSC_SUCCESS);
8435 }
8436 
8437 /*@
8438    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8439 
8440    Not Collective
8441 
8442    Input Parameters:
8443 +  A - the matrix we wish to propagate options from
8444 -  B - the matrix we wish to propagate options to
8445 
8446    Level: beginner
8447 
8448    Note:
8449    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8450 
8451 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8452 @*/
8453 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8454 {
8455   PetscFunctionBegin;
8456   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8457   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8458   B->symmetry_eternal            = A->symmetry_eternal;
8459   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8460   B->symmetric                   = A->symmetric;
8461   B->structurally_symmetric      = A->structurally_symmetric;
8462   B->spd                         = A->spd;
8463   B->hermitian                   = A->hermitian;
8464   PetscFunctionReturn(PETSC_SUCCESS);
8465 }
8466 
8467 /*@
8468    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8469    used during the assembly process to store values that belong to
8470    other processors.
8471 
8472    Not Collective
8473 
8474    Input Parameters:
8475 +  mat   - the matrix
8476 .  size  - the initial size of the stash.
8477 -  bsize - the initial size of the block-stash(if used).
8478 
8479    Options Database Keys:
8480 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8481 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8482 
8483    Level: intermediate
8484 
8485    Notes:
8486      The block-stash is used for values set with `MatSetValuesBlocked()` while
8487      the stash is used for values set with `MatSetValues()`
8488 
8489      Run with the option -info and look for output of the form
8490      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8491      to determine the appropriate value, MM, to use for size and
8492      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8493      to determine the value, BMM to use for bsize
8494 
8495 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8496 @*/
8497 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8498 {
8499   PetscFunctionBegin;
8500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8501   PetscValidType(mat, 1);
8502   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8503   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8504   PetscFunctionReturn(PETSC_SUCCESS);
8505 }
8506 
8507 /*@
8508    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8509      the matrix
8510 
8511    Neighbor-wise Collective
8512 
8513    Input Parameters:
8514 +  mat   - the matrix
8515 .  x - the vector to be multiplied by the interpolation operator
8516 -  y - the vector to be added to the result
8517 
8518    Output Parameter:
8519 .  w - the resulting vector
8520 
8521    Level: intermediate
8522 
8523    Notes:
8524     `w` may be the same vector as `y`.
8525 
8526     This allows one to use either the restriction or interpolation (its transpose)
8527     matrix to do the interpolation
8528 
8529 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8530 @*/
8531 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8532 {
8533   PetscInt M, N, Ny;
8534 
8535   PetscFunctionBegin;
8536   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8537   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8538   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8539   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8540   PetscCall(MatGetSize(A, &M, &N));
8541   PetscCall(VecGetSize(y, &Ny));
8542   if (M == Ny) {
8543     PetscCall(MatMultAdd(A, x, y, w));
8544   } else {
8545     PetscCall(MatMultTransposeAdd(A, x, y, w));
8546   }
8547   PetscFunctionReturn(PETSC_SUCCESS);
8548 }
8549 
8550 /*@
8551    MatInterpolate - y = A*x or A'*x depending on the shape of
8552      the matrix
8553 
8554    Neighbor-wise Collective
8555 
8556    Input Parameters:
8557 +  mat   - the matrix
8558 -  x - the vector to be interpolated
8559 
8560    Output Parameter:
8561 .  y - the resulting vector
8562 
8563    Level: intermediate
8564 
8565    Note:
8566     This allows one to use either the restriction or interpolation (its transpose)
8567     matrix to do the interpolation
8568 
8569 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8570 @*/
8571 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8572 {
8573   PetscInt M, N, Ny;
8574 
8575   PetscFunctionBegin;
8576   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8577   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8578   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8579   PetscCall(MatGetSize(A, &M, &N));
8580   PetscCall(VecGetSize(y, &Ny));
8581   if (M == Ny) {
8582     PetscCall(MatMult(A, x, y));
8583   } else {
8584     PetscCall(MatMultTranspose(A, x, y));
8585   }
8586   PetscFunctionReturn(PETSC_SUCCESS);
8587 }
8588 
8589 /*@
8590    MatRestrict - y = A*x or A'*x
8591 
8592    Neighbor-wise Collective
8593 
8594    Input Parameters:
8595 +  mat   - the matrix
8596 -  x - the vector to be restricted
8597 
8598    Output Parameter:
8599 .  y - the resulting vector
8600 
8601    Level: intermediate
8602 
8603    Note:
8604     This allows one to use either the restriction or interpolation (its transpose)
8605     matrix to do the restriction
8606 
8607 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8608 @*/
8609 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8610 {
8611   PetscInt M, N, Ny;
8612 
8613   PetscFunctionBegin;
8614   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8615   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8616   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8617   PetscCall(MatGetSize(A, &M, &N));
8618   PetscCall(VecGetSize(y, &Ny));
8619   if (M == Ny) {
8620     PetscCall(MatMult(A, x, y));
8621   } else {
8622     PetscCall(MatMultTranspose(A, x, y));
8623   }
8624   PetscFunctionReturn(PETSC_SUCCESS);
8625 }
8626 
8627 /*@
8628    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8629 
8630    Neighbor-wise Collective
8631 
8632    Input Parameters:
8633 +  mat   - the matrix
8634 .  x - the input dense matrix to be multiplied
8635 -  w - the input dense matrix to be added to the result
8636 
8637    Output Parameter:
8638 .  y - the output dense matrix
8639 
8640    Level: intermediate
8641 
8642    Note:
8643     This allows one to use either the restriction or interpolation (its transpose)
8644     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8645     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8646 
8647 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8648 @*/
8649 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8650 {
8651   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8652   PetscBool trans = PETSC_TRUE;
8653   MatReuse  reuse = MAT_INITIAL_MATRIX;
8654 
8655   PetscFunctionBegin;
8656   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8657   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8658   PetscValidType(x, 2);
8659   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8660   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8661   PetscCall(MatGetSize(A, &M, &N));
8662   PetscCall(MatGetSize(x, &Mx, &Nx));
8663   if (N == Mx) trans = PETSC_FALSE;
8664   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);
8665   Mo = trans ? N : M;
8666   if (*y) {
8667     PetscCall(MatGetSize(*y, &My, &Ny));
8668     if (Mo == My && Nx == Ny) {
8669       reuse = MAT_REUSE_MATRIX;
8670     } else {
8671       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);
8672       PetscCall(MatDestroy(y));
8673     }
8674   }
8675 
8676   if (w && *y == w) { /* this is to minimize changes in PCMG */
8677     PetscBool flg;
8678 
8679     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8680     if (w) {
8681       PetscInt My, Ny, Mw, Nw;
8682 
8683       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8684       PetscCall(MatGetSize(*y, &My, &Ny));
8685       PetscCall(MatGetSize(w, &Mw, &Nw));
8686       if (!flg || My != Mw || Ny != Nw) w = NULL;
8687     }
8688     if (!w) {
8689       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8690       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8691       PetscCall(PetscObjectDereference((PetscObject)w));
8692     } else {
8693       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8694     }
8695   }
8696   if (!trans) {
8697     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8698   } else {
8699     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8700   }
8701   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8702   PetscFunctionReturn(PETSC_SUCCESS);
8703 }
8704 
8705 /*@
8706    MatMatInterpolate - Y = A*X or A'*X
8707 
8708    Neighbor-wise Collective
8709 
8710    Input Parameters:
8711 +  mat   - the matrix
8712 -  x - the input dense matrix
8713 
8714    Output Parameter:
8715 .  y - the output dense matrix
8716 
8717    Level: intermediate
8718 
8719    Note:
8720     This allows one to use either the restriction or interpolation (its transpose)
8721     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8722     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8723 
8724 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8725 @*/
8726 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8727 {
8728   PetscFunctionBegin;
8729   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8730   PetscFunctionReturn(PETSC_SUCCESS);
8731 }
8732 
8733 /*@
8734    MatMatRestrict - Y = A*X or A'*X
8735 
8736    Neighbor-wise Collective
8737 
8738    Input Parameters:
8739 +  mat   - the matrix
8740 -  x - the input dense matrix
8741 
8742    Output Parameter:
8743 .  y - the output dense matrix
8744 
8745    Level: intermediate
8746 
8747    Note:
8748     This allows one to use either the restriction or interpolation (its transpose)
8749     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8750     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8751 
8752 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8753 @*/
8754 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8755 {
8756   PetscFunctionBegin;
8757   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8758   PetscFunctionReturn(PETSC_SUCCESS);
8759 }
8760 
8761 /*@
8762    MatGetNullSpace - retrieves the null space of a matrix.
8763 
8764    Logically Collective
8765 
8766    Input Parameters:
8767 +  mat - the matrix
8768 -  nullsp - the null space object
8769 
8770    Level: developer
8771 
8772 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8773 @*/
8774 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8775 {
8776   PetscFunctionBegin;
8777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8778   PetscValidPointer(nullsp, 2);
8779   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8780   PetscFunctionReturn(PETSC_SUCCESS);
8781 }
8782 
8783 /*@
8784    MatSetNullSpace - attaches a null space to a matrix.
8785 
8786    Logically Collective
8787 
8788    Input Parameters:
8789 +  mat - the matrix
8790 -  nullsp - the null space object
8791 
8792    Level: advanced
8793 
8794    Notes:
8795       This null space is used by the `KSP` linear solvers to solve singular systems.
8796 
8797       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`
8798 
8799       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
8800       to zero but the linear system will still be solved in a least squares sense.
8801 
8802       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8803    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).
8804    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
8805    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
8806    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).
8807    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8808 
8809     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8810     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8811     routine also automatically calls `MatSetTransposeNullSpace()`.
8812 
8813     The user should call `MatNullSpaceDestroy()`.
8814 
8815 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8816           `KSPSetPCSide()`
8817 @*/
8818 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8819 {
8820   PetscFunctionBegin;
8821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8822   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8823   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8824   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8825   mat->nullsp = nullsp;
8826   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8827   PetscFunctionReturn(PETSC_SUCCESS);
8828 }
8829 
8830 /*@
8831    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8832 
8833    Logically Collective
8834 
8835    Input Parameters:
8836 +  mat - the matrix
8837 -  nullsp - the null space object
8838 
8839    Level: developer
8840 
8841 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8842 @*/
8843 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8844 {
8845   PetscFunctionBegin;
8846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8847   PetscValidType(mat, 1);
8848   PetscValidPointer(nullsp, 2);
8849   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8850   PetscFunctionReturn(PETSC_SUCCESS);
8851 }
8852 
8853 /*@
8854    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8855 
8856    Logically Collective
8857 
8858    Input Parameters:
8859 +  mat - the matrix
8860 -  nullsp - the null space object
8861 
8862    Level: advanced
8863 
8864    Notes:
8865    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8866 
8867    See `MatSetNullSpace()`
8868 
8869 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8870 @*/
8871 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8872 {
8873   PetscFunctionBegin;
8874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8875   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8876   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8877   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8878   mat->transnullsp = nullsp;
8879   PetscFunctionReturn(PETSC_SUCCESS);
8880 }
8881 
8882 /*@
8883    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8884         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8885 
8886    Logically Collective
8887 
8888    Input Parameters:
8889 +  mat - the matrix
8890 -  nullsp - the null space object
8891 
8892    Level: advanced
8893 
8894    Notes:
8895    Overwrites any previous near null space that may have been attached
8896 
8897    You can remove the null space by calling this routine with an nullsp of `NULL`
8898 
8899 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8900 @*/
8901 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8902 {
8903   PetscFunctionBegin;
8904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8905   PetscValidType(mat, 1);
8906   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8907   MatCheckPreallocated(mat, 1);
8908   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8909   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8910   mat->nearnullsp = nullsp;
8911   PetscFunctionReturn(PETSC_SUCCESS);
8912 }
8913 
8914 /*@
8915    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8916 
8917    Not Collective
8918 
8919    Input Parameter:
8920 .  mat - the matrix
8921 
8922    Output Parameter:
8923 .  nullsp - the null space object, `NULL` if not set
8924 
8925    Level: advanced
8926 
8927 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8928 @*/
8929 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8930 {
8931   PetscFunctionBegin;
8932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8933   PetscValidType(mat, 1);
8934   PetscValidPointer(nullsp, 2);
8935   MatCheckPreallocated(mat, 1);
8936   *nullsp = mat->nearnullsp;
8937   PetscFunctionReturn(PETSC_SUCCESS);
8938 }
8939 
8940 /*@C
8941    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8942 
8943    Collective
8944 
8945    Input Parameters:
8946 +  mat - the matrix
8947 .  row - row/column permutation
8948 -  info - information on desired factorization process
8949 
8950    Notes:
8951    Probably really in-place only when level of fill is zero, otherwise allocates
8952    new space to store factored matrix and deletes previous memory.
8953 
8954    Most users should employ the `KSP` interface for linear solvers
8955    instead of working directly with matrix algebra routines such as this.
8956    See, e.g., `KSPCreate()`.
8957 
8958    Level: developer
8959 
8960    Developer Note:
8961    The Fortran interface is not autogenerated as the
8962    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8963 
8964 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8965 @*/
8966 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8967 {
8968   PetscFunctionBegin;
8969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8970   PetscValidType(mat, 1);
8971   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8972   PetscValidPointer(info, 3);
8973   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8974   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8975   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8976   MatCheckPreallocated(mat, 1);
8977   PetscUseTypeMethod(mat, iccfactor, row, info);
8978   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8979   PetscFunctionReturn(PETSC_SUCCESS);
8980 }
8981 
8982 /*@
8983    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8984          ghosted ones.
8985 
8986    Not Collective
8987 
8988    Input Parameters:
8989 +  mat - the matrix
8990 -  diag - the diagonal values, including ghost ones
8991 
8992    Level: developer
8993 
8994    Notes:
8995     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8996 
8997     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8998 
8999 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
9000 @*/
9001 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9002 {
9003   PetscMPIInt size;
9004 
9005   PetscFunctionBegin;
9006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9007   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9008   PetscValidType(mat, 1);
9009 
9010   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9011   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9012   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9013   if (size == 1) {
9014     PetscInt n, m;
9015     PetscCall(VecGetSize(diag, &n));
9016     PetscCall(MatGetSize(mat, NULL, &m));
9017     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9018     PetscCall(MatDiagonalScale(mat, NULL, diag));
9019   } else {
9020     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9021   }
9022   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9023   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9024   PetscFunctionReturn(PETSC_SUCCESS);
9025 }
9026 
9027 /*@
9028    MatGetInertia - Gets the inertia from a factored matrix
9029 
9030    Collective
9031 
9032    Input Parameter:
9033 .  mat - the matrix
9034 
9035    Output Parameters:
9036 +   nneg - number of negative eigenvalues
9037 .   nzero - number of zero eigenvalues
9038 -   npos - number of positive eigenvalues
9039 
9040    Level: advanced
9041 
9042    Note:
9043     Matrix must have been factored by `MatCholeskyFactor()`
9044 
9045 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9046 @*/
9047 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9048 {
9049   PetscFunctionBegin;
9050   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9051   PetscValidType(mat, 1);
9052   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9053   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9054   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9055   PetscFunctionReturn(PETSC_SUCCESS);
9056 }
9057 
9058 /*@C
9059    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9060 
9061    Neighbor-wise Collective
9062 
9063    Input Parameters:
9064 +  mat - the factored matrix obtained with `MatGetFactor()`
9065 -  b - the right-hand-side vectors
9066 
9067    Output Parameter:
9068 .  x - the result vectors
9069 
9070    Level: developer
9071 
9072    Note:
9073    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9074    call `MatSolves`(A,x,x).
9075 
9076 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9077 @*/
9078 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9079 {
9080   PetscFunctionBegin;
9081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9082   PetscValidType(mat, 1);
9083   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9084   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9085   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9086 
9087   MatCheckPreallocated(mat, 1);
9088   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9089   PetscUseTypeMethod(mat, solves, b, x);
9090   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9091   PetscFunctionReturn(PETSC_SUCCESS);
9092 }
9093 
9094 /*@
9095    MatIsSymmetric - Test whether a matrix is symmetric
9096 
9097    Collective
9098 
9099    Input Parameters:
9100 +  A - the matrix to test
9101 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9102 
9103    Output Parameter:
9104 .  flg - the result
9105 
9106    Level: intermediate
9107 
9108    Notes:
9109     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9110 
9111     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9112 
9113     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9114     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9115 
9116 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9117           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9118 @*/
9119 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9120 {
9121   PetscFunctionBegin;
9122   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9123   PetscValidBoolPointer(flg, 3);
9124 
9125   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9126   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9127   else {
9128     if (!A->ops->issymmetric) {
9129       MatType mattype;
9130       PetscCall(MatGetType(A, &mattype));
9131       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9132     }
9133     PetscUseTypeMethod(A, issymmetric, tol, flg);
9134     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9135   }
9136   PetscFunctionReturn(PETSC_SUCCESS);
9137 }
9138 
9139 /*@
9140    MatIsHermitian - Test whether a matrix is Hermitian
9141 
9142    Collective
9143 
9144    Input Parameters:
9145 +  A - the matrix to test
9146 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9147 
9148    Output Parameter:
9149 .  flg - the result
9150 
9151    Level: intermediate
9152 
9153    Notes:
9154     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9155 
9156     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9157 
9158     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9159     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9160 
9161 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9162           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9163 @*/
9164 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9165 {
9166   PetscFunctionBegin;
9167   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9168   PetscValidBoolPointer(flg, 3);
9169 
9170   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9171   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9172   else {
9173     if (!A->ops->ishermitian) {
9174       MatType mattype;
9175       PetscCall(MatGetType(A, &mattype));
9176       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9177     }
9178     PetscUseTypeMethod(A, ishermitian, tol, flg);
9179     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9180   }
9181   PetscFunctionReturn(PETSC_SUCCESS);
9182 }
9183 
9184 /*@
9185    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9186 
9187    Not Collective
9188 
9189    Input Parameter:
9190 .  A - the matrix to check
9191 
9192    Output Parameters:
9193 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9194 -  flg - the result (only valid if set is `PETSC_TRUE`)
9195 
9196    Level: advanced
9197 
9198    Notes:
9199    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9200    if you want it explicitly checked
9201 
9202     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9203     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9204 
9205 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9206 @*/
9207 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9208 {
9209   PetscFunctionBegin;
9210   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9211   PetscValidBoolPointer(set, 2);
9212   PetscValidBoolPointer(flg, 3);
9213   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9214     *set = PETSC_TRUE;
9215     *flg = PetscBool3ToBool(A->symmetric);
9216   } else {
9217     *set = PETSC_FALSE;
9218   }
9219   PetscFunctionReturn(PETSC_SUCCESS);
9220 }
9221 
9222 /*@
9223    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9224 
9225    Not Collective
9226 
9227    Input Parameter:
9228 .  A - the matrix to check
9229 
9230    Output Parameters:
9231 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9232 -  flg - the result (only valid if set is `PETSC_TRUE`)
9233 
9234    Level: advanced
9235 
9236    Notes:
9237    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9238 
9239    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9240    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9241 
9242 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9243 @*/
9244 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9245 {
9246   PetscFunctionBegin;
9247   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9248   PetscValidBoolPointer(set, 2);
9249   PetscValidBoolPointer(flg, 3);
9250   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9251     *set = PETSC_TRUE;
9252     *flg = PetscBool3ToBool(A->spd);
9253   } else {
9254     *set = PETSC_FALSE;
9255   }
9256   PetscFunctionReturn(PETSC_SUCCESS);
9257 }
9258 
9259 /*@
9260    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9261 
9262    Not Collective
9263 
9264    Input Parameter:
9265 .  A - the matrix to check
9266 
9267    Output Parameters:
9268 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9269 -  flg - the result (only valid if set is `PETSC_TRUE`)
9270 
9271    Level: advanced
9272 
9273    Notes:
9274    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9275    if you want it explicitly checked
9276 
9277    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9278    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9279 
9280 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9281 @*/
9282 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9283 {
9284   PetscFunctionBegin;
9285   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9286   PetscValidBoolPointer(set, 2);
9287   PetscValidBoolPointer(flg, 3);
9288   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9289     *set = PETSC_TRUE;
9290     *flg = PetscBool3ToBool(A->hermitian);
9291   } else {
9292     *set = PETSC_FALSE;
9293   }
9294   PetscFunctionReturn(PETSC_SUCCESS);
9295 }
9296 
9297 /*@
9298    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9299 
9300    Collective
9301 
9302    Input Parameter:
9303 .  A - the matrix to test
9304 
9305    Output Parameter:
9306 .  flg - the result
9307 
9308    Level: intermediate
9309 
9310    Notes:
9311    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9312 
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 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9317 @*/
9318 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9319 {
9320   PetscFunctionBegin;
9321   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9322   PetscValidBoolPointer(flg, 2);
9323   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9324     *flg = PetscBool3ToBool(A->structurally_symmetric);
9325   } else {
9326     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9327     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9328   }
9329   PetscFunctionReturn(PETSC_SUCCESS);
9330 }
9331 
9332 /*@
9333    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9334 
9335    Not Collective
9336 
9337    Input Parameter:
9338 .  A - the matrix to check
9339 
9340    Output Parameters:
9341 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9342 -  flg - the result (only valid if set is PETSC_TRUE)
9343 
9344    Level: advanced
9345 
9346    Notes:
9347    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
9348    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9349 
9350    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9351 
9352 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9353 @*/
9354 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9355 {
9356   PetscFunctionBegin;
9357   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9358   PetscValidBoolPointer(set, 2);
9359   PetscValidBoolPointer(flg, 3);
9360   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9361     *set = PETSC_TRUE;
9362     *flg = PetscBool3ToBool(A->structurally_symmetric);
9363   } else {
9364     *set = PETSC_FALSE;
9365   }
9366   PetscFunctionReturn(PETSC_SUCCESS);
9367 }
9368 
9369 /*@
9370    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9371        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9372 
9373     Not Collective
9374 
9375    Input Parameter:
9376 .   mat - the matrix
9377 
9378    Output Parameters:
9379 +   nstash   - the size of the stash
9380 .   reallocs - the number of additional mallocs incurred.
9381 .   bnstash   - the size of the block stash
9382 -   breallocs - the number of additional mallocs incurred.in the block stash
9383 
9384    Level: advanced
9385 
9386 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9387 @*/
9388 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9389 {
9390   PetscFunctionBegin;
9391   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9392   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9393   PetscFunctionReturn(PETSC_SUCCESS);
9394 }
9395 
9396 /*@C
9397    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9398    parallel layout, `PetscLayout` for rows and columns
9399 
9400    Collective
9401 
9402    Input Parameter:
9403 .  mat - the matrix
9404 
9405    Output Parameters:
9406 +   right - (optional) vector that the matrix can be multiplied against
9407 -   left - (optional) vector that the matrix vector product can be stored in
9408 
9409   Level: advanced
9410 
9411    Notes:
9412     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()`.
9413 
9414     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9415 
9416 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9417 @*/
9418 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9419 {
9420   PetscFunctionBegin;
9421   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9422   PetscValidType(mat, 1);
9423   if (mat->ops->getvecs) {
9424     PetscUseTypeMethod(mat, getvecs, right, left);
9425   } else {
9426     PetscInt rbs, cbs;
9427     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9428     if (right) {
9429       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9430       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9431       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9432       PetscCall(VecSetBlockSize(*right, cbs));
9433       PetscCall(VecSetType(*right, mat->defaultvectype));
9434 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9435       if (mat->boundtocpu && mat->bindingpropagates) {
9436         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9437         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9438       }
9439 #endif
9440       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9441     }
9442     if (left) {
9443       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9444       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9445       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9446       PetscCall(VecSetBlockSize(*left, rbs));
9447       PetscCall(VecSetType(*left, mat->defaultvectype));
9448 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9449       if (mat->boundtocpu && mat->bindingpropagates) {
9450         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9451         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9452       }
9453 #endif
9454       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9455     }
9456   }
9457   PetscFunctionReturn(PETSC_SUCCESS);
9458 }
9459 
9460 /*@C
9461    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9462      with default values.
9463 
9464    Not Collective
9465 
9466    Input Parameters:
9467 .    info - the `MatFactorInfo` data structure
9468 
9469    Level: developer
9470 
9471    Notes:
9472     The solvers are generally used through the `KSP` and `PC` objects, for example
9473           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9474 
9475     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9476 
9477    Developer Note:
9478    The Fortran interface is not autogenerated as the
9479    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9480 
9481 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9482 @*/
9483 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9484 {
9485   PetscFunctionBegin;
9486   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9487   PetscFunctionReturn(PETSC_SUCCESS);
9488 }
9489 
9490 /*@
9491    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9492 
9493    Collective
9494 
9495    Input Parameters:
9496 +  mat - the factored matrix
9497 -  is - the index set defining the Schur indices (0-based)
9498 
9499    Level: advanced
9500 
9501    Notes:
9502     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9503 
9504    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9505 
9506    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9507 
9508 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9509           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9510 @*/
9511 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9512 {
9513   PetscErrorCode (*f)(Mat, IS);
9514 
9515   PetscFunctionBegin;
9516   PetscValidType(mat, 1);
9517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9518   PetscValidType(is, 2);
9519   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9520   PetscCheckSameComm(mat, 1, is, 2);
9521   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9522   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9523   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9524   PetscCall(MatDestroy(&mat->schur));
9525   PetscCall((*f)(mat, is));
9526   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9527   PetscFunctionReturn(PETSC_SUCCESS);
9528 }
9529 
9530 /*@
9531   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9532 
9533    Logically Collective
9534 
9535    Input Parameters:
9536 +  F - the factored matrix obtained by calling `MatGetFactor()`
9537 .  S - location where to return the Schur complement, can be `NULL`
9538 -  status - the status of the Schur complement matrix, can be `NULL`
9539 
9540    Level: advanced
9541 
9542    Notes:
9543    You must call `MatFactorSetSchurIS()` before calling this routine.
9544 
9545    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9546 
9547    The routine provides a copy of the Schur matrix stored within the solver data structures.
9548    The caller must destroy the object when it is no longer needed.
9549    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9550 
9551    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)
9552 
9553    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9554 
9555    Developer Note:
9556     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9557    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9558 
9559 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9560 @*/
9561 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9562 {
9563   PetscFunctionBegin;
9564   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9565   if (S) PetscValidPointer(S, 2);
9566   if (status) PetscValidPointer(status, 3);
9567   if (S) {
9568     PetscErrorCode (*f)(Mat, Mat *);
9569 
9570     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9571     if (f) {
9572       PetscCall((*f)(F, S));
9573     } else {
9574       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9575     }
9576   }
9577   if (status) *status = F->schur_status;
9578   PetscFunctionReturn(PETSC_SUCCESS);
9579 }
9580 
9581 /*@
9582   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9583 
9584    Logically Collective
9585 
9586    Input Parameters:
9587 +  F - the factored matrix obtained by calling `MatGetFactor()`
9588 .  *S - location where to return the Schur complement, can be `NULL`
9589 -  status - the status of the Schur complement matrix, can be `NULL`
9590 
9591    Level: advanced
9592 
9593    Notes:
9594    You must call `MatFactorSetSchurIS()` before calling this routine.
9595 
9596    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9597 
9598    The routine returns a the Schur Complement stored within the data structures of the solver.
9599 
9600    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9601 
9602    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9603 
9604    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9605 
9606    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9607 
9608 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9609 @*/
9610 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9611 {
9612   PetscFunctionBegin;
9613   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9614   if (S) PetscValidPointer(S, 2);
9615   if (status) PetscValidPointer(status, 3);
9616   if (S) *S = F->schur;
9617   if (status) *status = F->schur_status;
9618   PetscFunctionReturn(PETSC_SUCCESS);
9619 }
9620 
9621 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9622 {
9623   Mat S = F->schur;
9624 
9625   PetscFunctionBegin;
9626   switch (F->schur_status) {
9627   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9628   case MAT_FACTOR_SCHUR_INVERTED:
9629     if (S) {
9630       S->ops->solve             = NULL;
9631       S->ops->matsolve          = NULL;
9632       S->ops->solvetranspose    = NULL;
9633       S->ops->matsolvetranspose = NULL;
9634       S->ops->solveadd          = NULL;
9635       S->ops->solvetransposeadd = NULL;
9636       S->factortype             = MAT_FACTOR_NONE;
9637       PetscCall(PetscFree(S->solvertype));
9638     }
9639   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9640     break;
9641   default:
9642     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9643   }
9644   PetscFunctionReturn(PETSC_SUCCESS);
9645 }
9646 
9647 /*@
9648   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9649 
9650    Logically Collective
9651 
9652    Input Parameters:
9653 +  F - the factored matrix obtained by calling `MatGetFactor()`
9654 .  *S - location where the Schur complement is stored
9655 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9656 
9657    Level: advanced
9658 
9659 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9660 @*/
9661 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9662 {
9663   PetscFunctionBegin;
9664   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9665   if (S) {
9666     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9667     *S = NULL;
9668   }
9669   F->schur_status = status;
9670   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9671   PetscFunctionReturn(PETSC_SUCCESS);
9672 }
9673 
9674 /*@
9675   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9676 
9677    Logically Collective
9678 
9679    Input Parameters:
9680 +  F - the factored matrix obtained by calling `MatGetFactor()`
9681 .  rhs - location where the right hand side of the Schur complement system is stored
9682 -  sol - location where the solution of the Schur complement system has to be returned
9683 
9684    Level: advanced
9685 
9686    Notes:
9687    The sizes of the vectors should match the size of the Schur complement
9688 
9689    Must be called after `MatFactorSetSchurIS()`
9690 
9691 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9692 @*/
9693 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9694 {
9695   PetscFunctionBegin;
9696   PetscValidType(F, 1);
9697   PetscValidType(rhs, 2);
9698   PetscValidType(sol, 3);
9699   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9700   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9701   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9702   PetscCheckSameComm(F, 1, rhs, 2);
9703   PetscCheckSameComm(F, 1, sol, 3);
9704   PetscCall(MatFactorFactorizeSchurComplement(F));
9705   switch (F->schur_status) {
9706   case MAT_FACTOR_SCHUR_FACTORED:
9707     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9708     break;
9709   case MAT_FACTOR_SCHUR_INVERTED:
9710     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9711     break;
9712   default:
9713     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9714   }
9715   PetscFunctionReturn(PETSC_SUCCESS);
9716 }
9717 
9718 /*@
9719   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9720 
9721    Logically Collective
9722 
9723    Input Parameters:
9724 +  F - the factored matrix obtained by calling `MatGetFactor()`
9725 .  rhs - location where the right hand side of the Schur complement system is stored
9726 -  sol - location where the solution of the Schur complement system has to be returned
9727 
9728    Level: advanced
9729 
9730    Notes:
9731    The sizes of the vectors should match the size of the Schur complement
9732 
9733    Must be called after `MatFactorSetSchurIS()`
9734 
9735 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9736 @*/
9737 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9738 {
9739   PetscFunctionBegin;
9740   PetscValidType(F, 1);
9741   PetscValidType(rhs, 2);
9742   PetscValidType(sol, 3);
9743   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9744   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9745   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9746   PetscCheckSameComm(F, 1, rhs, 2);
9747   PetscCheckSameComm(F, 1, sol, 3);
9748   PetscCall(MatFactorFactorizeSchurComplement(F));
9749   switch (F->schur_status) {
9750   case MAT_FACTOR_SCHUR_FACTORED:
9751     PetscCall(MatSolve(F->schur, rhs, sol));
9752     break;
9753   case MAT_FACTOR_SCHUR_INVERTED:
9754     PetscCall(MatMult(F->schur, rhs, sol));
9755     break;
9756   default:
9757     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9758   }
9759   PetscFunctionReturn(PETSC_SUCCESS);
9760 }
9761 
9762 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9763 #if PetscDefined(HAVE_CUDA)
9764 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9765 #endif
9766 
9767 /* Schur status updated in the interface */
9768 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9769 {
9770   Mat S = F->schur;
9771 
9772   PetscFunctionBegin;
9773   if (S) {
9774     PetscMPIInt size;
9775     PetscBool   isdense, isdensecuda;
9776 
9777     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9778     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9779     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9780     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9781     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9782     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9783     if (isdense) {
9784       PetscCall(MatSeqDenseInvertFactors_Private(S));
9785     } else if (isdensecuda) {
9786 #if defined(PETSC_HAVE_CUDA)
9787       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9788 #endif
9789     }
9790     // HIP??????????????
9791     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9792   }
9793   PetscFunctionReturn(PETSC_SUCCESS);
9794 }
9795 
9796 /*@
9797   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9798 
9799    Logically Collective
9800 
9801    Input Parameters:
9802 .  F - the factored matrix obtained by calling `MatGetFactor()`
9803 
9804    Level: advanced
9805 
9806    Notes:
9807     Must be called after `MatFactorSetSchurIS()`.
9808 
9809    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9810 
9811 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9812 @*/
9813 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9814 {
9815   PetscFunctionBegin;
9816   PetscValidType(F, 1);
9817   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9818   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9819   PetscCall(MatFactorFactorizeSchurComplement(F));
9820   PetscCall(MatFactorInvertSchurComplement_Private(F));
9821   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9822   PetscFunctionReturn(PETSC_SUCCESS);
9823 }
9824 
9825 /*@
9826   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9827 
9828    Logically Collective
9829 
9830    Input Parameters:
9831 .  F - the factored matrix obtained by calling `MatGetFactor()`
9832 
9833    Level: advanced
9834 
9835    Note:
9836     Must be called after `MatFactorSetSchurIS()`
9837 
9838 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9839 @*/
9840 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9841 {
9842   MatFactorInfo info;
9843 
9844   PetscFunctionBegin;
9845   PetscValidType(F, 1);
9846   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9847   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9848   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9849   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9850   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9851     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9852   } else {
9853     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9854   }
9855   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9856   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9857   PetscFunctionReturn(PETSC_SUCCESS);
9858 }
9859 
9860 /*@
9861    MatPtAP - Creates the matrix product C = P^T * A * P
9862 
9863    Neighbor-wise Collective
9864 
9865    Input Parameters:
9866 +  A - the matrix
9867 .  P - the projection matrix
9868 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9869 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9870           if the result is a dense matrix this is irrelevant
9871 
9872    Output Parameter:
9873 .  C - the product matrix
9874 
9875    Level: intermediate
9876 
9877    Notes:
9878    C will be created and must be destroyed by the user with `MatDestroy()`.
9879 
9880    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9881 
9882    Developer Note:
9883    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9884 
9885 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9886 @*/
9887 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9888 {
9889   PetscFunctionBegin;
9890   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9891   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9892 
9893   if (scall == MAT_INITIAL_MATRIX) {
9894     PetscCall(MatProductCreate(A, P, NULL, C));
9895     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9896     PetscCall(MatProductSetAlgorithm(*C, "default"));
9897     PetscCall(MatProductSetFill(*C, fill));
9898 
9899     (*C)->product->api_user = PETSC_TRUE;
9900     PetscCall(MatProductSetFromOptions(*C));
9901     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);
9902     PetscCall(MatProductSymbolic(*C));
9903   } else { /* scall == MAT_REUSE_MATRIX */
9904     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9905   }
9906 
9907   PetscCall(MatProductNumeric(*C));
9908   (*C)->symmetric = A->symmetric;
9909   (*C)->spd       = A->spd;
9910   PetscFunctionReturn(PETSC_SUCCESS);
9911 }
9912 
9913 /*@
9914    MatRARt - Creates the matrix product C = R * A * R^T
9915 
9916    Neighbor-wise Collective
9917 
9918    Input Parameters:
9919 +  A - the matrix
9920 .  R - the projection matrix
9921 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9922 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9923           if the result is a dense matrix this is irrelevant
9924 
9925    Output Parameter:
9926 .  C - the product matrix
9927 
9928    Level: intermediate
9929 
9930    Notes:
9931    C will be created and must be destroyed by the user with `MatDestroy()`.
9932 
9933    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9934 
9935    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9936    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9937    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9938    We recommend using MatPtAP().
9939 
9940 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9941 @*/
9942 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9943 {
9944   PetscFunctionBegin;
9945   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9946   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9947 
9948   if (scall == MAT_INITIAL_MATRIX) {
9949     PetscCall(MatProductCreate(A, R, NULL, C));
9950     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9951     PetscCall(MatProductSetAlgorithm(*C, "default"));
9952     PetscCall(MatProductSetFill(*C, fill));
9953 
9954     (*C)->product->api_user = PETSC_TRUE;
9955     PetscCall(MatProductSetFromOptions(*C));
9956     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);
9957     PetscCall(MatProductSymbolic(*C));
9958   } else { /* scall == MAT_REUSE_MATRIX */
9959     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9960   }
9961 
9962   PetscCall(MatProductNumeric(*C));
9963   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9964   PetscFunctionReturn(PETSC_SUCCESS);
9965 }
9966 
9967 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9968 {
9969   PetscFunctionBegin;
9970   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9971 
9972   if (scall == MAT_INITIAL_MATRIX) {
9973     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9974     PetscCall(MatProductCreate(A, B, NULL, C));
9975     PetscCall(MatProductSetType(*C, ptype));
9976     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9977     PetscCall(MatProductSetFill(*C, fill));
9978 
9979     (*C)->product->api_user = PETSC_TRUE;
9980     PetscCall(MatProductSetFromOptions(*C));
9981     PetscCall(MatProductSymbolic(*C));
9982   } else { /* scall == MAT_REUSE_MATRIX */
9983     Mat_Product *product = (*C)->product;
9984     PetscBool    isdense;
9985 
9986     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9987     if (isdense && product && product->type != ptype) {
9988       PetscCall(MatProductClear(*C));
9989       product = NULL;
9990     }
9991     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9992     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9993       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9994       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9995       product           = (*C)->product;
9996       product->fill     = fill;
9997       product->api_user = PETSC_TRUE;
9998       product->clear    = PETSC_TRUE;
9999 
10000       PetscCall(MatProductSetType(*C, ptype));
10001       PetscCall(MatProductSetFromOptions(*C));
10002       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);
10003       PetscCall(MatProductSymbolic(*C));
10004     } else { /* user may change input matrices A or B when REUSE */
10005       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10006     }
10007   }
10008   PetscCall(MatProductNumeric(*C));
10009   PetscFunctionReturn(PETSC_SUCCESS);
10010 }
10011 
10012 /*@
10013    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10014 
10015    Neighbor-wise Collective
10016 
10017    Input Parameters:
10018 +  A - the left matrix
10019 .  B - the right matrix
10020 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10021 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10022           if the result is a dense matrix this is irrelevant
10023 
10024    Output Parameter:
10025 .  C - the product matrix
10026 
10027    Notes:
10028    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10029 
10030    `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
10031    call to this function with `MAT_INITIAL_MATRIX`.
10032 
10033    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10034 
10035    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`,
10036    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10037 
10038    Example of Usage:
10039 .vb
10040      MatProductCreate(A,B,NULL,&C);
10041      MatProductSetType(C,MATPRODUCT_AB);
10042      MatProductSymbolic(C);
10043      MatProductNumeric(C); // compute C=A * B
10044      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10045      MatProductNumeric(C);
10046      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10047      MatProductNumeric(C);
10048 .ve
10049 
10050    Level: intermediate
10051 
10052 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10053 @*/
10054 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10055 {
10056   PetscFunctionBegin;
10057   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10058   PetscFunctionReturn(PETSC_SUCCESS);
10059 }
10060 
10061 /*@
10062    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10063 
10064    Neighbor-wise Collective
10065 
10066    Input Parameters:
10067 +  A - the left matrix
10068 .  B - the right matrix
10069 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10070 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10071 
10072    Output Parameter:
10073 .  C - the product matrix
10074 
10075    Level: intermediate
10076 
10077    Notes:
10078    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10079 
10080    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10081 
10082    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10083    actually needed.
10084 
10085    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10086    and for pairs of `MATMPIDENSE` matrices.
10087 
10088    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10089 
10090    Options Database Keys:
10091 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10092               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10093               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10094 
10095 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10096 @*/
10097 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10098 {
10099   PetscFunctionBegin;
10100   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10101   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10102   PetscFunctionReturn(PETSC_SUCCESS);
10103 }
10104 
10105 /*@
10106    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10107 
10108    Neighbor-wise Collective
10109 
10110    Input Parameters:
10111 +  A - the left matrix
10112 .  B - the right matrix
10113 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10114 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10115 
10116    Output Parameters:
10117 .  C - the product matrix
10118 
10119    Level: intermediate
10120 
10121    Notes:
10122    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10123 
10124    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10125 
10126    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10127 
10128    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10129    actually needed.
10130 
10131    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10132    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10133 
10134 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10135 @*/
10136 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10137 {
10138   PetscFunctionBegin;
10139   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10140   PetscFunctionReturn(PETSC_SUCCESS);
10141 }
10142 
10143 /*@
10144    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10145 
10146    Neighbor-wise Collective
10147 
10148    Input Parameters:
10149 +  A - the left matrix
10150 .  B - the middle matrix
10151 .  C - the right matrix
10152 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10153 -  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
10154           if the result is a dense matrix this is irrelevant
10155 
10156    Output Parameters:
10157 .  D - the product matrix
10158 
10159    Level: intermediate
10160 
10161    Notes:
10162    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10163 
10164    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10165 
10166    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10167 
10168    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10169    actually needed.
10170 
10171    If you have many matrices with the same non-zero structure to multiply, you
10172    should use `MAT_REUSE_MATRIX` in all calls but the first
10173 
10174 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10175 @*/
10176 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10177 {
10178   PetscFunctionBegin;
10179   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10180   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10181 
10182   if (scall == MAT_INITIAL_MATRIX) {
10183     PetscCall(MatProductCreate(A, B, C, D));
10184     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10185     PetscCall(MatProductSetAlgorithm(*D, "default"));
10186     PetscCall(MatProductSetFill(*D, fill));
10187 
10188     (*D)->product->api_user = PETSC_TRUE;
10189     PetscCall(MatProductSetFromOptions(*D));
10190     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,
10191                ((PetscObject)C)->type_name);
10192     PetscCall(MatProductSymbolic(*D));
10193   } else { /* user may change input matrices when REUSE */
10194     PetscCall(MatProductReplaceMats(A, B, C, *D));
10195   }
10196   PetscCall(MatProductNumeric(*D));
10197   PetscFunctionReturn(PETSC_SUCCESS);
10198 }
10199 
10200 /*@
10201    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10202 
10203    Collective
10204 
10205    Input Parameters:
10206 +  mat - the matrix
10207 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10208 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10209 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10210 
10211    Output Parameter:
10212 .  matredundant - redundant matrix
10213 
10214    Level: advanced
10215 
10216    Notes:
10217    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10218    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10219 
10220    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10221    calling it.
10222 
10223    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10224 
10225 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10226 @*/
10227 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10228 {
10229   MPI_Comm       comm;
10230   PetscMPIInt    size;
10231   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10232   Mat_Redundant *redund     = NULL;
10233   PetscSubcomm   psubcomm   = NULL;
10234   MPI_Comm       subcomm_in = subcomm;
10235   Mat           *matseq;
10236   IS             isrow, iscol;
10237   PetscBool      newsubcomm = PETSC_FALSE;
10238 
10239   PetscFunctionBegin;
10240   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10241   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10242     PetscValidPointer(*matredundant, 5);
10243     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10244   }
10245 
10246   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10247   if (size == 1 || nsubcomm == 1) {
10248     if (reuse == MAT_INITIAL_MATRIX) {
10249       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10250     } else {
10251       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");
10252       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10253     }
10254     PetscFunctionReturn(PETSC_SUCCESS);
10255   }
10256 
10257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10259   MatCheckPreallocated(mat, 1);
10260 
10261   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10262   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10263     /* create psubcomm, then get subcomm */
10264     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10265     PetscCallMPI(MPI_Comm_size(comm, &size));
10266     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10267 
10268     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10269     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10270     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10271     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10272     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10273     newsubcomm = PETSC_TRUE;
10274     PetscCall(PetscSubcommDestroy(&psubcomm));
10275   }
10276 
10277   /* get isrow, iscol and a local sequential matrix matseq[0] */
10278   if (reuse == MAT_INITIAL_MATRIX) {
10279     mloc_sub = PETSC_DECIDE;
10280     nloc_sub = PETSC_DECIDE;
10281     if (bs < 1) {
10282       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10283       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10284     } else {
10285       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10286       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10287     }
10288     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10289     rstart = rend - mloc_sub;
10290     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10291     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10292   } else { /* reuse == MAT_REUSE_MATRIX */
10293     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");
10294     /* retrieve subcomm */
10295     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10296     redund = (*matredundant)->redundant;
10297     isrow  = redund->isrow;
10298     iscol  = redund->iscol;
10299     matseq = redund->matseq;
10300   }
10301   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10302 
10303   /* get matredundant over subcomm */
10304   if (reuse == MAT_INITIAL_MATRIX) {
10305     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10306 
10307     /* create a supporting struct and attach it to C for reuse */
10308     PetscCall(PetscNew(&redund));
10309     (*matredundant)->redundant = redund;
10310     redund->isrow              = isrow;
10311     redund->iscol              = iscol;
10312     redund->matseq             = matseq;
10313     if (newsubcomm) {
10314       redund->subcomm = subcomm;
10315     } else {
10316       redund->subcomm = MPI_COMM_NULL;
10317     }
10318   } else {
10319     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10320   }
10321 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10322   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10323     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10324     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10325   }
10326 #endif
10327   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10328   PetscFunctionReturn(PETSC_SUCCESS);
10329 }
10330 
10331 /*@C
10332    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10333    a given `Mat`. Each submatrix can span multiple procs.
10334 
10335    Collective
10336 
10337    Input Parameters:
10338 +  mat - the matrix
10339 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10340 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10341 
10342    Output Parameter:
10343 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10344 
10345   Level: advanced
10346 
10347   Notes:
10348   The submatrix partition across processors is dictated by `subComm` a
10349   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10350   is not restricted to be grouped with consecutive original ranks.
10351 
10352   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10353   map directly to the layout of the original matrix [wrt the local
10354   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10355   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10356   the `subMat`. However the offDiagMat looses some columns - and this is
10357   reconstructed with `MatSetValues()`
10358 
10359   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10360 
10361 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10362 @*/
10363 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10364 {
10365   PetscMPIInt commsize, subCommSize;
10366 
10367   PetscFunctionBegin;
10368   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10369   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10370   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10371 
10372   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");
10373   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10374   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10375   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10376   PetscFunctionReturn(PETSC_SUCCESS);
10377 }
10378 
10379 /*@
10380    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10381 
10382    Not Collective
10383 
10384    Input Parameters:
10385 +  mat - matrix to extract local submatrix from
10386 .  isrow - local row indices for submatrix
10387 -  iscol - local column indices for submatrix
10388 
10389    Output Parameter:
10390 .  submat - the submatrix
10391 
10392    Level: intermediate
10393 
10394    Notes:
10395    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10396 
10397    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10398    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10399 
10400    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10401    `MatSetValuesBlockedLocal()` will also be implemented.
10402 
10403    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10404    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10405 
10406 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10407 @*/
10408 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10409 {
10410   PetscFunctionBegin;
10411   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10412   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10413   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10414   PetscCheckSameComm(isrow, 2, iscol, 3);
10415   PetscValidPointer(submat, 4);
10416   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10417 
10418   if (mat->ops->getlocalsubmatrix) {
10419     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10420   } else {
10421     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10422   }
10423   PetscFunctionReturn(PETSC_SUCCESS);
10424 }
10425 
10426 /*@
10427    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10428 
10429    Not Collective
10430 
10431    Input Parameters:
10432 +  mat - matrix to extract local submatrix from
10433 .  isrow - local row indices for submatrix
10434 .  iscol - local column indices for submatrix
10435 -  submat - the submatrix
10436 
10437    Level: intermediate
10438 
10439 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10440 @*/
10441 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10442 {
10443   PetscFunctionBegin;
10444   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10445   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10446   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10447   PetscCheckSameComm(isrow, 2, iscol, 3);
10448   PetscValidPointer(submat, 4);
10449   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10450 
10451   if (mat->ops->restorelocalsubmatrix) {
10452     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10453   } else {
10454     PetscCall(MatDestroy(submat));
10455   }
10456   *submat = NULL;
10457   PetscFunctionReturn(PETSC_SUCCESS);
10458 }
10459 
10460 /*@
10461    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10462 
10463    Collective
10464 
10465    Input Parameter:
10466 .  mat - the matrix
10467 
10468    Output Parameter:
10469 .  is - if any rows have zero diagonals this contains the list of them
10470 
10471    Level: developer
10472 
10473 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10474 @*/
10475 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10476 {
10477   PetscFunctionBegin;
10478   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10479   PetscValidType(mat, 1);
10480   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10481   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10482 
10483   if (!mat->ops->findzerodiagonals) {
10484     Vec                diag;
10485     const PetscScalar *a;
10486     PetscInt          *rows;
10487     PetscInt           rStart, rEnd, r, nrow = 0;
10488 
10489     PetscCall(MatCreateVecs(mat, &diag, NULL));
10490     PetscCall(MatGetDiagonal(mat, diag));
10491     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10492     PetscCall(VecGetArrayRead(diag, &a));
10493     for (r = 0; r < rEnd - rStart; ++r)
10494       if (a[r] == 0.0) ++nrow;
10495     PetscCall(PetscMalloc1(nrow, &rows));
10496     nrow = 0;
10497     for (r = 0; r < rEnd - rStart; ++r)
10498       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10499     PetscCall(VecRestoreArrayRead(diag, &a));
10500     PetscCall(VecDestroy(&diag));
10501     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10502   } else {
10503     PetscUseTypeMethod(mat, findzerodiagonals, is);
10504   }
10505   PetscFunctionReturn(PETSC_SUCCESS);
10506 }
10507 
10508 /*@
10509    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10510 
10511    Collective
10512 
10513    Input Parameter:
10514 .  mat - the matrix
10515 
10516    Output Parameter:
10517 .  is - contains the list of rows with off block diagonal entries
10518 
10519    Level: developer
10520 
10521 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10522 @*/
10523 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10524 {
10525   PetscFunctionBegin;
10526   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10527   PetscValidType(mat, 1);
10528   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10529   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10530 
10531   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10532   PetscFunctionReturn(PETSC_SUCCESS);
10533 }
10534 
10535 /*@C
10536   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10537 
10538   Collective; No Fortran Support
10539 
10540   Input Parameters:
10541 . mat - the matrix
10542 
10543   Output Parameters:
10544 . values - the block inverses in column major order (FORTRAN-like)
10545 
10546   Level: advanced
10547 
10548    Notes:
10549    The size of the blocks is determined by the block size of the matrix.
10550 
10551    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10552 
10553    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10554 
10555 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10556 @*/
10557 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10558 {
10559   PetscFunctionBegin;
10560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10561   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10562   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10563   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10564   PetscFunctionReturn(PETSC_SUCCESS);
10565 }
10566 
10567 /*@C
10568   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10569 
10570   Collective; No Fortran Support
10571 
10572   Input Parameters:
10573 + mat - the matrix
10574 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10575 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10576 
10577   Output Parameters:
10578 . values - the block inverses in column major order (FORTRAN-like)
10579 
10580   Level: advanced
10581 
10582   Notes:
10583   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10584 
10585   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10586 
10587 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10588 @*/
10589 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10590 {
10591   PetscFunctionBegin;
10592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10593   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10594   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10595   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10596   PetscFunctionReturn(PETSC_SUCCESS);
10597 }
10598 
10599 /*@
10600   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10601 
10602   Collective
10603 
10604   Input Parameters:
10605 + A - the matrix
10606 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10607 
10608   Level: advanced
10609 
10610   Note:
10611   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10612 
10613 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10614 @*/
10615 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10616 {
10617   const PetscScalar *vals;
10618   PetscInt          *dnnz;
10619   PetscInt           m, rstart, rend, bs, i, j;
10620 
10621   PetscFunctionBegin;
10622   PetscCall(MatInvertBlockDiagonal(A, &vals));
10623   PetscCall(MatGetBlockSize(A, &bs));
10624   PetscCall(MatGetLocalSize(A, &m, NULL));
10625   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10626   PetscCall(PetscMalloc1(m / bs, &dnnz));
10627   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10628   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10629   PetscCall(PetscFree(dnnz));
10630   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10631   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10632   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10633   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10634   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10635   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10636   PetscFunctionReturn(PETSC_SUCCESS);
10637 }
10638 
10639 /*@C
10640     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10641     via `MatTransposeColoringCreate()`.
10642 
10643     Collective
10644 
10645     Input Parameter:
10646 .   c - coloring context
10647 
10648     Level: intermediate
10649 
10650 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10651 @*/
10652 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10653 {
10654   MatTransposeColoring matcolor = *c;
10655 
10656   PetscFunctionBegin;
10657   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10658   if (--((PetscObject)matcolor)->refct > 0) {
10659     matcolor = NULL;
10660     PetscFunctionReturn(PETSC_SUCCESS);
10661   }
10662 
10663   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10664   PetscCall(PetscFree(matcolor->rows));
10665   PetscCall(PetscFree(matcolor->den2sp));
10666   PetscCall(PetscFree(matcolor->colorforcol));
10667   PetscCall(PetscFree(matcolor->columns));
10668   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10669   PetscCall(PetscHeaderDestroy(c));
10670   PetscFunctionReturn(PETSC_SUCCESS);
10671 }
10672 
10673 /*@C
10674     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10675     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10676     `MatTransposeColoring` to sparse B.
10677 
10678     Collective
10679 
10680     Input Parameters:
10681 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10682 -   B - sparse matrix
10683 
10684     Output Parameter:
10685 .   Btdense - dense matrix B^T
10686 
10687     Level: developer
10688 
10689     Note:
10690     These are used internally for some implementations of `MatRARt()`
10691 
10692 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10693 @*/
10694 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10695 {
10696   PetscFunctionBegin;
10697   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10698   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10699   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10700 
10701   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10702   PetscFunctionReturn(PETSC_SUCCESS);
10703 }
10704 
10705 /*@C
10706     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10707     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10708     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10709     `Csp` from `Cden`.
10710 
10711     Collective
10712 
10713     Input Parameters:
10714 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10715 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10716 
10717     Output Parameter:
10718 .   Csp - sparse matrix
10719 
10720     Level: developer
10721 
10722     Note:
10723     These are used internally for some implementations of `MatRARt()`
10724 
10725 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10726 @*/
10727 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10728 {
10729   PetscFunctionBegin;
10730   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10731   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10732   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10733 
10734   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10735   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10736   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10737   PetscFunctionReturn(PETSC_SUCCESS);
10738 }
10739 
10740 /*@C
10741    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10742 
10743    Collective
10744 
10745    Input Parameters:
10746 +  mat - the matrix product C
10747 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10748 
10749     Output Parameter:
10750 .   color - the new coloring context
10751 
10752     Level: intermediate
10753 
10754 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10755           `MatTransColoringApplyDenToSp()`
10756 @*/
10757 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10758 {
10759   MatTransposeColoring c;
10760   MPI_Comm             comm;
10761 
10762   PetscFunctionBegin;
10763   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10764   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10765   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10766 
10767   c->ctype = iscoloring->ctype;
10768   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10769 
10770   *color = c;
10771   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10772   PetscFunctionReturn(PETSC_SUCCESS);
10773 }
10774 
10775 /*@
10776       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10777         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10778         same, otherwise it will be larger
10779 
10780      Not Collective
10781 
10782   Input Parameter:
10783 .    A  - the matrix
10784 
10785   Output Parameter:
10786 .    state - the current state
10787 
10788   Level: intermediate
10789 
10790   Notes:
10791     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10792          different matrices
10793 
10794     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10795 
10796     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10797 
10798 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10799 @*/
10800 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10801 {
10802   PetscFunctionBegin;
10803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10804   *state = mat->nonzerostate;
10805   PetscFunctionReturn(PETSC_SUCCESS);
10806 }
10807 
10808 /*@
10809       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10810                  matrices from each processor
10811 
10812     Collective
10813 
10814    Input Parameters:
10815 +    comm - the communicators the parallel matrix will live on
10816 .    seqmat - the input sequential matrices
10817 .    n - number of local columns (or `PETSC_DECIDE`)
10818 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10819 
10820    Output Parameter:
10821 .    mpimat - the parallel matrix generated
10822 
10823     Level: developer
10824 
10825    Note:
10826     The number of columns of the matrix in EACH processor MUST be the same.
10827 
10828 .seealso: [](chapter_matrices), `Mat`
10829 @*/
10830 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10831 {
10832   PetscMPIInt size;
10833 
10834   PetscFunctionBegin;
10835   PetscCallMPI(MPI_Comm_size(comm, &size));
10836   if (size == 1) {
10837     if (reuse == MAT_INITIAL_MATRIX) {
10838       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10839     } else {
10840       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10841     }
10842     PetscFunctionReturn(PETSC_SUCCESS);
10843   }
10844 
10845   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");
10846 
10847   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10848   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10849   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10850   PetscFunctionReturn(PETSC_SUCCESS);
10851 }
10852 
10853 /*@
10854      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10855 
10856     Collective
10857 
10858    Input Parameters:
10859 +    A   - the matrix to create subdomains from
10860 -    N   - requested number of subdomains
10861 
10862    Output Parameters:
10863 +    n   - number of subdomains resulting on this rank
10864 -    iss - `IS` list with indices of subdomains on this rank
10865 
10866     Level: advanced
10867 
10868     Note:
10869     The number of subdomains must be smaller than the communicator size
10870 
10871 .seealso: [](chapter_matrices), `Mat`, `IS`
10872 @*/
10873 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10874 {
10875   MPI_Comm    comm, subcomm;
10876   PetscMPIInt size, rank, color;
10877   PetscInt    rstart, rend, k;
10878 
10879   PetscFunctionBegin;
10880   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10881   PetscCallMPI(MPI_Comm_size(comm, &size));
10882   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10883   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);
10884   *n    = 1;
10885   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10886   color = rank / k;
10887   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10888   PetscCall(PetscMalloc1(1, iss));
10889   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10890   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10891   PetscCallMPI(MPI_Comm_free(&subcomm));
10892   PetscFunctionReturn(PETSC_SUCCESS);
10893 }
10894 
10895 /*@
10896    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10897 
10898    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10899    If they are not the same, uses `MatMatMatMult()`.
10900 
10901    Once the coarse grid problem is constructed, correct for interpolation operators
10902    that are not of full rank, which can legitimately happen in the case of non-nested
10903    geometric multigrid.
10904 
10905    Input Parameters:
10906 +  restrct - restriction operator
10907 .  dA - fine grid matrix
10908 .  interpolate - interpolation operator
10909 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10910 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10911 
10912    Output Parameters:
10913 .  A - the Galerkin coarse matrix
10914 
10915    Options Database Key:
10916 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10917 
10918    Level: developer
10919 
10920 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10921 @*/
10922 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10923 {
10924   IS  zerorows;
10925   Vec diag;
10926 
10927   PetscFunctionBegin;
10928   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10929   /* Construct the coarse grid matrix */
10930   if (interpolate == restrct) {
10931     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10932   } else {
10933     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10934   }
10935 
10936   /* If the interpolation matrix is not of full rank, A will have zero rows.
10937      This can legitimately happen in the case of non-nested geometric multigrid.
10938      In that event, we set the rows of the matrix to the rows of the identity,
10939      ignoring the equations (as the RHS will also be zero). */
10940 
10941   PetscCall(MatFindZeroRows(*A, &zerorows));
10942 
10943   if (zerorows != NULL) { /* if there are any zero rows */
10944     PetscCall(MatCreateVecs(*A, &diag, NULL));
10945     PetscCall(MatGetDiagonal(*A, diag));
10946     PetscCall(VecISSet(diag, zerorows, 1.0));
10947     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10948     PetscCall(VecDestroy(&diag));
10949     PetscCall(ISDestroy(&zerorows));
10950   }
10951   PetscFunctionReturn(PETSC_SUCCESS);
10952 }
10953 
10954 /*@C
10955     MatSetOperation - Allows user to set a matrix operation for any matrix type
10956 
10957    Logically Collective
10958 
10959     Input Parameters:
10960 +   mat - the matrix
10961 .   op - the name of the operation
10962 -   f - the function that provides the operation
10963 
10964    Level: developer
10965 
10966     Usage:
10967 .vb
10968   extern PetscErrorCode usermult(Mat, Vec, Vec);
10969 
10970   PetscCall(MatCreateXXX(comm, ..., &A));
10971   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10972 .ve
10973 
10974     Notes:
10975     See the file `include/petscmat.h` for a complete list of matrix
10976     operations, which all have the form MATOP_<OPERATION>, where
10977     <OPERATION> is the name (in all capital letters) of the
10978     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10979 
10980     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10981     sequence as the usual matrix interface routines, since they
10982     are intended to be accessed via the usual matrix interface
10983     routines, e.g.,
10984 .vb
10985   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10986 .ve
10987 
10988     In particular each function MUST return `PETSC_SUCCESS` on success and
10989     nonzero on failure.
10990 
10991     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10992 
10993 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10994 @*/
10995 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10996 {
10997   PetscFunctionBegin;
10998   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10999   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11000   (((void (**)(void))mat->ops)[op]) = f;
11001   PetscFunctionReturn(PETSC_SUCCESS);
11002 }
11003 
11004 /*@C
11005     MatGetOperation - Gets a matrix operation for any matrix type.
11006 
11007     Not Collective
11008 
11009     Input Parameters:
11010 +   mat - the matrix
11011 -   op - the name of the operation
11012 
11013     Output Parameter:
11014 .   f - the function that provides the operation
11015 
11016     Level: developer
11017 
11018     Usage:
11019 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
11020 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
11021 
11022     Notes:
11023     See the file include/petscmat.h for a complete list of matrix
11024     operations, which all have the form MATOP_<OPERATION>, where
11025     <OPERATION> is the name (in all capital letters) of the
11026     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11027 
11028     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11029 
11030 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11031 @*/
11032 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11033 {
11034   PetscFunctionBegin;
11035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11036   *f = (((void (**)(void))mat->ops)[op]);
11037   PetscFunctionReturn(PETSC_SUCCESS);
11038 }
11039 
11040 /*@
11041     MatHasOperation - Determines whether the given matrix supports the particular operation.
11042 
11043    Not Collective
11044 
11045    Input Parameters:
11046 +  mat - the matrix
11047 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11048 
11049    Output Parameter:
11050 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11051 
11052    Level: advanced
11053 
11054    Note:
11055    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11056 
11057 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11058 @*/
11059 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11060 {
11061   PetscFunctionBegin;
11062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11063   PetscValidBoolPointer(has, 3);
11064   if (mat->ops->hasoperation) {
11065     PetscUseTypeMethod(mat, hasoperation, op, has);
11066   } else {
11067     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11068     else {
11069       *has = PETSC_FALSE;
11070       if (op == MATOP_CREATE_SUBMATRIX) {
11071         PetscMPIInt size;
11072 
11073         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11074         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11075       }
11076     }
11077   }
11078   PetscFunctionReturn(PETSC_SUCCESS);
11079 }
11080 
11081 /*@
11082     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11083 
11084    Collective
11085 
11086    Input Parameters:
11087 .  mat - the matrix
11088 
11089    Output Parameter:
11090 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11091 
11092    Level: beginner
11093 
11094 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11095 @*/
11096 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11097 {
11098   PetscFunctionBegin;
11099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11100   PetscValidType(mat, 1);
11101   PetscValidBoolPointer(cong, 2);
11102   if (!mat->rmap || !mat->cmap) {
11103     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11104     PetscFunctionReturn(PETSC_SUCCESS);
11105   }
11106   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11107     PetscCall(PetscLayoutSetUp(mat->rmap));
11108     PetscCall(PetscLayoutSetUp(mat->cmap));
11109     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11110     if (*cong) mat->congruentlayouts = 1;
11111     else mat->congruentlayouts = 0;
11112   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11113   PetscFunctionReturn(PETSC_SUCCESS);
11114 }
11115 
11116 PetscErrorCode MatSetInf(Mat A)
11117 {
11118   PetscFunctionBegin;
11119   PetscUseTypeMethod(A, setinf);
11120   PetscFunctionReturn(PETSC_SUCCESS);
11121 }
11122 
11123 /*@C
11124    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
11125    and possibly removes small values from the graph structure.
11126 
11127    Collective
11128 
11129    Input Parameters:
11130 +  A - the matrix
11131 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11132 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11133 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11134 
11135    Output Parameter:
11136 .  graph - the resulting graph
11137 
11138    Level: advanced
11139 
11140 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11141 @*/
11142 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11143 {
11144   PetscFunctionBegin;
11145   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11146   PetscValidType(A, 1);
11147   PetscValidLogicalCollectiveBool(A, scale, 3);
11148   PetscValidPointer(graph, 5);
11149   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11150   PetscFunctionReturn(PETSC_SUCCESS);
11151 }
11152 
11153 /*@
11154   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11155   meaning the same memory is used for the matrix, and no new memory is allocated.
11156 
11157   Collective
11158 
11159   Input Parameter:
11160 . A - the matrix
11161 
11162   Level: intermediate
11163 
11164   Developer Note:
11165   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11166   of the arrays in the data structure are unneeded.
11167 
11168 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11169 @*/
11170 PetscErrorCode MatEliminateZeros(Mat A)
11171 {
11172   PetscFunctionBegin;
11173   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11174   PetscUseTypeMethod(A, eliminatezeros);
11175   PetscFunctionReturn(PETSC_SUCCESS);
11176 }
11177