xref: /petsc/src/mat/interface/matrix.c (revision 0b149c5a8b9d6677364cc77e4bab2aa4eff9cdd8)
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. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
52                   for sparse matrices that already have locations it fills the locations with random numbers
53 
54    Logically Collective on mat
55 
56    Input Parameters:
57 +  x  - the matrix
58 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
59           it will create one internally.
60 
61    Output Parameter:
62 .  x  - the matrix
63 
64    Example of Usage:
65 .vb
66      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
67      MatSetRandom(x,rctx);
68      PetscRandomDestroy(rctx);
69 .ve
70 
71    Level: intermediate
72 
73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
74 @*/
75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
76 {
77   PetscRandom randObj = NULL;
78 
79   PetscFunctionBegin;
80   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
81   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
82   PetscValidType(x, 1);
83   MatCheckPreallocated(x, 1);
84 
85   if (!rctx) {
86     MPI_Comm comm;
87     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
88     PetscCall(PetscRandomCreate(comm, &randObj));
89     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
90     PetscCall(PetscRandomSetFromOptions(randObj));
91     rctx = randObj;
92   }
93   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
94   PetscUseTypeMethod(x, setrandom, rctx);
95   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
96 
97   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
98   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
99   PetscCall(PetscRandomDestroy(&randObj));
100   PetscFunctionReturn(0);
101 }
102 
103 /*@
104    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
105 
106    Logically Collective on mat
107 
108    Input Parameter:
109 .  mat - the factored matrix
110 
111    Output Parameters:
112 +  pivot - the pivot value computed
113 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
114          the share the matrix
115 
116    Level: advanced
117 
118    Notes:
119     This routine does not work for factorizations done with external packages.
120 
121     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
122 
123     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
124 
125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
126           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
127 @*/
128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
129 {
130   PetscFunctionBegin;
131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
132   PetscValidRealPointer(pivot, 2);
133   PetscValidIntPointer(row, 3);
134   *pivot = mat->factorerror_zeropivot_value;
135   *row   = mat->factorerror_zeropivot_row;
136   PetscFunctionReturn(0);
137 }
138 
139 /*@
140    MatFactorGetError - gets the error code from a factorization
141 
142    Logically Collective on mat
143 
144    Input Parameters:
145 .  mat - the factored matrix
146 
147    Output Parameter:
148 .  err  - the error code
149 
150    Level: advanced
151 
152    Note:
153     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
154 
155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
156           `MatFactorError`
157 @*/
158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
159 {
160   PetscFunctionBegin;
161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
162   PetscValidPointer(err, 2);
163   *err = mat->factorerrortype;
164   PetscFunctionReturn(0);
165 }
166 
167 /*@
168    MatFactorClearError - clears the error code in a factorization
169 
170    Logically Collective on mat
171 
172    Input Parameter:
173 .  mat - the factored matrix
174 
175    Level: developer
176 
177    Note:
178     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
179 
180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
181           `MatGetErrorCode()`, `MatFactorError`
182 @*/
183 PetscErrorCode MatFactorClearError(Mat mat)
184 {
185   PetscFunctionBegin;
186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
187   mat->factorerrortype             = MAT_FACTOR_NOERROR;
188   mat->factorerror_zeropivot_value = 0.0;
189   mat->factorerror_zeropivot_row   = 0;
190   PetscFunctionReturn(0);
191 }
192 
193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
194 {
195   Vec                r, l;
196   const PetscScalar *al;
197   PetscInt           i, nz, gnz, N, n;
198 
199   PetscFunctionBegin;
200   PetscCall(MatCreateVecs(mat, &r, &l));
201   if (!cols) { /* nonzero rows */
202     PetscCall(MatGetSize(mat, &N, NULL));
203     PetscCall(MatGetLocalSize(mat, &n, NULL));
204     PetscCall(VecSet(l, 0.0));
205     PetscCall(VecSetRandom(r, NULL));
206     PetscCall(MatMult(mat, r, l));
207     PetscCall(VecGetArrayRead(l, &al));
208   } else { /* nonzero columns */
209     PetscCall(MatGetSize(mat, NULL, &N));
210     PetscCall(MatGetLocalSize(mat, NULL, &n));
211     PetscCall(VecSet(r, 0.0));
212     PetscCall(VecSetRandom(l, NULL));
213     PetscCall(MatMultTranspose(mat, l, r));
214     PetscCall(VecGetArrayRead(r, &al));
215   }
216   if (tol <= 0.0) {
217     for (i = 0, nz = 0; i < n; i++)
218       if (al[i] != 0.0) nz++;
219   } else {
220     for (i = 0, nz = 0; i < n; i++)
221       if (PetscAbsScalar(al[i]) > tol) nz++;
222   }
223   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
224   if (gnz != N) {
225     PetscInt *nzr;
226     PetscCall(PetscMalloc1(nz, &nzr));
227     if (nz) {
228       if (tol < 0) {
229         for (i = 0, nz = 0; i < n; i++)
230           if (al[i] != 0.0) nzr[nz++] = i;
231       } else {
232         for (i = 0, nz = 0; i < n; i++)
233           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
234       }
235     }
236     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
237   } else *nonzero = NULL;
238   if (!cols) { /* nonzero rows */
239     PetscCall(VecRestoreArrayRead(l, &al));
240   } else {
241     PetscCall(VecRestoreArrayRead(r, &al));
242   }
243   PetscCall(VecDestroy(&l));
244   PetscCall(VecDestroy(&r));
245   PetscFunctionReturn(0);
246 }
247 
248 /*@
249       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
250 
251   Input Parameter:
252 .    A  - the matrix
253 
254   Output Parameter:
255 .    keptrows - the rows that are not completely zero
256 
257   Note:
258     keptrows is set to NULL if all rows are nonzero.
259 
260   Level: intermediate
261 
262 .seealso: `Mat`, `MatFindZeroRows()`
263  @*/
264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
265 {
266   PetscFunctionBegin;
267   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
268   PetscValidType(mat, 1);
269   PetscValidPointer(keptrows, 2);
270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
271   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
272   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
273   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
274   PetscFunctionReturn(0);
275 }
276 
277 /*@
278       MatFindZeroRows - Locate all rows that are completely zero in the matrix
279 
280   Input Parameter:
281 .    A  - the matrix
282 
283   Output Parameter:
284 .    zerorows - the rows that are completely zero
285 
286   Note:
287     zerorows is set to NULL if no rows are zero.
288 
289   Level: intermediate
290 
291 .seealso: `Mat`, `MatFindNonzeroRows()`
292  @*/
293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
294 {
295   IS       keptrows;
296   PetscInt m, n;
297 
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
300   PetscValidType(mat, 1);
301   PetscValidPointer(zerorows, 2);
302   PetscCall(MatFindNonzeroRows(mat, &keptrows));
303   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
304      In keeping with this convention, we set zerorows to NULL if there are no zero
305      rows. */
306   if (keptrows == NULL) {
307     *zerorows = NULL;
308   } else {
309     PetscCall(MatGetOwnershipRange(mat, &m, &n));
310     PetscCall(ISComplement(keptrows, m, n, zerorows));
311     PetscCall(ISDestroy(&keptrows));
312   }
313   PetscFunctionReturn(0);
314 }
315 
316 /*@
317    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
318 
319    Not Collective
320 
321    Input Parameters:
322 .   A - the matrix
323 
324    Output Parameters:
325 .   a - the diagonal part (which is a SEQUENTIAL matrix)
326 
327    Notes:
328    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
329 
330    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
331 
332    Level: advanced
333 
334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
335 @*/
336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
337 {
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
340   PetscValidType(A, 1);
341   PetscValidPointer(a, 2);
342   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
343   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
344   else {
345     PetscMPIInt size;
346 
347     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
348     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
349     *a = A;
350   }
351   PetscFunctionReturn(0);
352 }
353 
354 /*@
355    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
356 
357    Collective on mat
358 
359    Input Parameters:
360 .  mat - the matrix
361 
362    Output Parameter:
363 .   trace - the sum of the diagonal entries
364 
365    Level: advanced
366 
367 .seealso: `Mat`
368 @*/
369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
370 {
371   Vec diag;
372 
373   PetscFunctionBegin;
374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
375   PetscValidScalarPointer(trace, 2);
376   PetscCall(MatCreateVecs(mat, &diag, NULL));
377   PetscCall(MatGetDiagonal(mat, diag));
378   PetscCall(VecSum(diag, trace));
379   PetscCall(VecDestroy(&diag));
380   PetscFunctionReturn(0);
381 }
382 
383 /*@
384    MatRealPart - Zeros out the imaginary part of the matrix
385 
386    Logically Collective on mat
387 
388    Input Parameters:
389 .  mat - the matrix
390 
391    Level: advanced
392 
393 .seealso: `MatImaginaryPart()`
394 @*/
395 PetscErrorCode MatRealPart(Mat mat)
396 {
397   PetscFunctionBegin;
398   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
399   PetscValidType(mat, 1);
400   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
401   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
402   MatCheckPreallocated(mat, 1);
403   PetscUseTypeMethod(mat, realpart);
404   PetscFunctionReturn(0);
405 }
406 
407 /*@C
408    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
409 
410    Collective on mat
411 
412    Input Parameter:
413 .  mat - the matrix
414 
415    Output Parameters:
416 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
417 -   ghosts - the global indices of the ghost points
418 
419    Note:
420     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
421 
422    Level: advanced
423 
424 .seealso: `Mat`, `VecCreateGhost()`
425 @*/
426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
427 {
428   PetscFunctionBegin;
429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
430   PetscValidType(mat, 1);
431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
433   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
434   else {
435     if (nghosts) *nghosts = 0;
436     if (ghosts) *ghosts = NULL;
437   }
438   PetscFunctionReturn(0);
439 }
440 
441 /*@
442    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
443 
444    Logically Collective on mat
445 
446    Input Parameters:
447 .  mat - the matrix
448 
449    Level: advanced
450 
451 .seealso: `MatRealPart()`
452 @*/
453 PetscErrorCode MatImaginaryPart(Mat mat)
454 {
455   PetscFunctionBegin;
456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
457   PetscValidType(mat, 1);
458   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
459   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
460   MatCheckPreallocated(mat, 1);
461   PetscUseTypeMethod(mat, imaginarypart);
462   PetscFunctionReturn(0);
463 }
464 
465 /*@
466    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
467 
468    Not Collective
469 
470    Input Parameter:
471 .  mat - the matrix
472 
473    Output Parameters:
474 +  missing - is any diagonal missing
475 -  dd - first diagonal entry that is missing (optional) on this process
476 
477    Level: advanced
478 
479 .seealso: `Mat`
480 @*/
481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
482 {
483   PetscFunctionBegin;
484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
485   PetscValidType(mat, 1);
486   PetscValidBoolPointer(missing, 2);
487   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
488   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
489   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
490   PetscFunctionReturn(0);
491 }
492 
493 /*@C
494    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
495    for each row that you get to ensure that your application does
496    not bleed memory.
497 
498    Not Collective
499 
500    Input Parameters:
501 +  mat - the matrix
502 -  row - the row to get
503 
504    Output Parameters:
505 +  ncols -  if not NULL, the number of nonzeros in the row
506 .  cols - if not NULL, the column numbers
507 -  vals - if not NULL, the values
508 
509    Notes:
510    This routine is provided for people who need to have direct access
511    to the structure of a matrix.  We hope that we provide enough
512    high-level matrix routines that few users will need it.
513 
514    `MatGetRow()` always returns 0-based column indices, regardless of
515    whether the internal representation is 0-based (default) or 1-based.
516 
517    For better efficiency, set cols and/or vals to NULL if you do
518    not wish to extract these quantities.
519 
520    The user can only examine the values extracted with `MatGetRow()`;
521    the values cannot be altered.  To change the matrix entries, one
522    must use `MatSetValues()`.
523 
524    You can only have one call to `MatGetRow()` outstanding for a particular
525    matrix at a time, per processor. `MatGetRow()` can only obtain rows
526    associated with the given processor, it cannot get rows from the
527    other processors; for that we suggest using `MatCreateSubMatrices()`, then
528    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
529    is in the global number of rows.
530 
531    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
532 
533    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
534 
535    Fortran Note:
536    The calling sequence from Fortran is
537 .vb
538    MatGetRow(matrix,row,ncols,cols,values,ierr)
539          Mat     matrix (input)
540          integer row    (input)
541          integer ncols  (output)
542          integer cols(maxcols) (output)
543          double precision (or double complex) values(maxcols) output
544 .ve
545    where maxcols >= maximum nonzeros in any row of the matrix.
546 
547    Caution:
548    Do not try to change the contents of the output arrays (cols and vals).
549    In some cases, this may corrupt the matrix.
550 
551    Level: advanced
552 
553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
554 @*/
555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
556 {
557   PetscInt incols;
558 
559   PetscFunctionBegin;
560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
561   PetscValidType(mat, 1);
562   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
563   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
564   MatCheckPreallocated(mat, 1);
565   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);
566   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
567   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
568   if (ncols) *ncols = incols;
569   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
570   PetscFunctionReturn(0);
571 }
572 
573 /*@
574    MatConjugate - replaces the matrix values with their complex conjugates
575 
576    Logically Collective on mat
577 
578    Input Parameters:
579 .  mat - the matrix
580 
581    Level: advanced
582 
583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
584 @*/
585 PetscErrorCode MatConjugate(Mat mat)
586 {
587   PetscFunctionBegin;
588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
590   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
591     PetscUseTypeMethod(mat, conjugate);
592     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
593   }
594   PetscFunctionReturn(0);
595 }
596 
597 /*@C
598    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
599 
600    Not Collective
601 
602    Input Parameters:
603 +  mat - the matrix
604 .  row - the row to get
605 .  ncols, cols - the number of nonzeros and their columns
606 -  vals - if nonzero the column values
607 
608    Notes:
609    This routine should be called after you have finished examining the entries.
610 
611    This routine zeros out ncols, cols, and vals. This is to prevent accidental
612    us of the array after it has been restored. If you pass NULL, it will
613    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
614 
615    Fortran Notes:
616    The calling sequence from Fortran is
617 .vb
618    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
619       Mat     matrix (input)
620       integer row    (input)
621       integer ncols  (output)
622       integer cols(maxcols) (output)
623       double precision (or double complex) values(maxcols) output
624 .ve
625    Where maxcols >= maximum nonzeros in any row of the matrix.
626 
627    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
628    before another call to `MatGetRow()` can be made.
629 
630    Level: advanced
631 
632 .seealso: `MatGetRow()`
633 @*/
634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
635 {
636   PetscFunctionBegin;
637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
638   if (ncols) PetscValidIntPointer(ncols, 3);
639   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
640   if (!mat->ops->restorerow) PetscFunctionReturn(0);
641   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
642   if (ncols) *ncols = 0;
643   if (cols) *cols = NULL;
644   if (vals) *vals = NULL;
645   PetscFunctionReturn(0);
646 }
647 
648 /*@
649    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
650    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
651 
652    Not Collective
653 
654    Input Parameters:
655 .  mat - the matrix
656 
657    Note:
658    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.
659 
660    Level: advanced
661 
662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
663 @*/
664 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
665 {
666   PetscFunctionBegin;
667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
668   PetscValidType(mat, 1);
669   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
670   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
671   MatCheckPreallocated(mat, 1);
672   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
673   PetscUseTypeMethod(mat, getrowuppertriangular);
674   PetscFunctionReturn(0);
675 }
676 
677 /*@
678    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
679 
680    Not Collective
681 
682    Input Parameters:
683 .  mat - the matrix
684 
685    Note:
686    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
687 
688    Level: advanced
689 
690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
701   PetscUseTypeMethod(mat, restorerowuppertriangular);
702   PetscFunctionReturn(0);
703 }
704 
705 /*@C
706    MatSetOptionsPrefix - Sets the prefix used for searching for all
707    `Mat` options in the database.
708 
709    Logically Collective on A
710 
711    Input Parameters:
712 +  A - the matrix
713 -  prefix - the prefix to prepend to all option names
714 
715    Notes:
716    A hyphen (-) must NOT be given at the beginning of the prefix name.
717    The first character of all runtime options is AUTOMATICALLY the hyphen.
718 
719    This is NOT used for options for the factorization of the matrix. Normally the
720    prefix is automatically passed in from the PC calling the factorization. To set
721    it directly use  `MatSetOptionsPrefixFactor()`
722 
723    Level: advanced
724 
725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
726 @*/
727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
728 {
729   PetscFunctionBegin;
730   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
731   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
732   PetscFunctionReturn(0);
733 }
734 
735 /*@C
736    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
737    for matrices created with `MatGetFactor()`
738 
739    Logically Collective on A
740 
741    Input Parameters:
742 +  A - the matrix
743 -  prefix - the prefix to prepend to all option names for the factored matrix
744 
745    Notes:
746    A hyphen (-) must NOT be given at the beginning of the prefix name.
747    The first character of all runtime options is AUTOMATICALLY the hyphen.
748 
749    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
750    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
751 
752    Level: developer
753 
754 .seealso:   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
755 @*/
756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
757 {
758   PetscFunctionBegin;
759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
760   if (prefix) {
761     PetscValidCharPointer(prefix, 2);
762     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
763     if (prefix != A->factorprefix) {
764       PetscCall(PetscFree(A->factorprefix));
765       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
766     }
767   } else PetscCall(PetscFree(A->factorprefix));
768   PetscFunctionReturn(0);
769 }
770 
771 /*@C
772    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
773    for matrices created with `MatGetFactor()`
774 
775    Logically Collective on A
776 
777    Input Parameters:
778 +  A - the matrix
779 -  prefix - the prefix to prepend to all option names for the factored matrix
780 
781    Notes:
782    A hyphen (-) must NOT be given at the beginning of the prefix name.
783    The first character of all runtime options is AUTOMATICALLY the hyphen.
784 
785    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
786    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
787 
788    Level: developer
789 
790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
791           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
792           `MatSetOptionsPrefix()`
793 @*/
794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
795 {
796   char  *buf = A->factorprefix;
797   size_t len1, len2;
798 
799   PetscFunctionBegin;
800   PetscValidHeader(A, 1);
801   if (!prefix) PetscFunctionReturn(0);
802   if (!buf) {
803     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
804     PetscFunctionReturn(0);
805   }
806   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
807 
808   PetscCall(PetscStrlen(prefix, &len1));
809   PetscCall(PetscStrlen(buf, &len2));
810   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
811   PetscCall(PetscStrcpy(A->factorprefix, buf));
812   PetscCall(PetscStrcat(A->factorprefix, prefix));
813   PetscCall(PetscFree(buf));
814   PetscFunctionReturn(0);
815 }
816 
817 /*@C
818    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
819    matrix options in the database.
820 
821    Logically Collective on A
822 
823    Input Parameters:
824 +  A - the matrix
825 -  prefix - the prefix to prepend to all option names
826 
827    Note:
828    A hyphen (-) must NOT be given at the beginning of the prefix name.
829    The first character of all runtime options is AUTOMATICALLY the hyphen.
830 
831    Level: advanced
832 
833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
834 @*/
835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
836 {
837   PetscFunctionBegin;
838   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
839   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
840   PetscFunctionReturn(0);
841 }
842 
843 /*@C
844    MatGetOptionsPrefix - Gets the prefix used for searching for all
845    matrix options in the database.
846 
847    Not Collective
848 
849    Input Parameter:
850 .  A - the matrix
851 
852    Output Parameter:
853 .  prefix - pointer to the prefix string used
854 
855    Fortran Note:
856     On the fortran side, the user should pass in a string 'prefix' of
857    sufficient length to hold the prefix.
858 
859    Level: advanced
860 
861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
862 @*/
863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
864 {
865   PetscFunctionBegin;
866   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
867   PetscValidPointer(prefix, 2);
868   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
869   PetscFunctionReturn(0);
870 }
871 
872 /*@
873    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
874 
875    Collective on A
876 
877    Input Parameters:
878 .  A - the matrix
879 
880    Notes:
881    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
882 
883    Users can reset the preallocation to access the original memory.
884 
885    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
886 
887    Level: beginner
888 
889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
890 @*/
891 PetscErrorCode MatResetPreallocation(Mat A)
892 {
893   PetscFunctionBegin;
894   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
895   PetscValidType(A, 1);
896   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
897   PetscFunctionReturn(0);
898 }
899 
900 /*@
901    MatSetUp - Sets up the internal matrix data structures for later use.
902 
903    Collective on A
904 
905    Input Parameters:
906 .  A - the matrix
907 
908    Notes:
909    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
910 
911    If a suitable preallocation routine is used, this function does not need to be called.
912 
913    See the Performance chapter of the PETSc users manual for how to preallocate matrices
914 
915    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
916 
917    Level: intermediate
918 
919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
920 @*/
921 PetscErrorCode MatSetUp(Mat A)
922 {
923   PetscFunctionBegin;
924   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
925   if (!((PetscObject)A)->type_name) {
926     PetscMPIInt size;
927 
928     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
929     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
930   }
931   if (!A->preallocated && A->ops->setup) {
932     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
933     PetscUseTypeMethod(A, setup);
934   }
935   PetscCall(PetscLayoutSetUp(A->rmap));
936   PetscCall(PetscLayoutSetUp(A->cmap));
937   A->preallocated = PETSC_TRUE;
938   PetscFunctionReturn(0);
939 }
940 
941 #if defined(PETSC_HAVE_SAWS)
942   #include <petscviewersaws.h>
943 #endif
944 
945 /*@C
946    MatViewFromOptions - View properties of the matrix from the options database
947 
948    Collective on A
949 
950    Input Parameters:
951 +  A - the matrix
952 .  obj - optional additional object that provides the options prefix to use
953 -  name - command line option
954 
955   Options Database:
956 .  -mat_view [viewertype]:... - the viewer and its options
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    Level: intermediate
971 
972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
973 @*/
974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
975 {
976   PetscFunctionBegin;
977   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
978   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
979   PetscFunctionReturn(0);
980 }
981 
982 /*@C
983    MatView - display information about a matrix in a variety ways
984 
985    Collective on mat
986 
987    Input Parameters:
988 +  mat - the matrix
989 -  viewer - visualization context
990 
991   Notes:
992   The available visualization contexts include
993 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
994 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
995 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
996 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
997 
998    The user can open alternative visualization contexts with
999 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1000 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1001          specified file; corresponding input uses MatLoad()
1002 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1003          an X window display
1004 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1005          Currently only the sequential dense and AIJ
1006          matrix types support the Socket viewer.
1007 
1008    The user can call `PetscViewerPushFormat()` to specify the output
1009    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1010    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1011 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1012 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1013 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1014 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1015          format common among all matrix types
1016 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1017          format (which is in many cases the same as the default)
1018 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1019          size and structure (not the matrix entries)
1020 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1021          the matrix structure
1022 
1023    Options Database Keys:
1024 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1025 .  -mat_view ::ascii_info_detail - Prints more detailed info
1026 .  -mat_view - Prints matrix in ASCII format
1027 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1028 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1029 .  -display <name> - Sets display name (default is host)
1030 .  -draw_pause <sec> - Sets number of seconds to pause after display
1031 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1032 .  -viewer_socket_machine <machine> -
1033 .  -viewer_socket_port <port> -
1034 .  -mat_view binary - save matrix to file in binary format
1035 -  -viewer_binary_filename <name> -
1036 
1037    Level: beginner
1038 
1039    Notes:
1040     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1041     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1042 
1043     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1044 
1045     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1046       viewer is used.
1047 
1048       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1049       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1050 
1051       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1052       and then use the following mouse functions.
1053 .vb
1054   left mouse: zoom in
1055   middle mouse: zoom out
1056   right mouse: continue with the simulation
1057 .ve
1058 
1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1060           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1061 @*/
1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1063 {
1064   PetscInt          rows, cols, rbs, cbs;
1065   PetscBool         isascii, isstring, issaws;
1066   PetscViewerFormat format;
1067   PetscMPIInt       size;
1068 
1069   PetscFunctionBegin;
1070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1071   PetscValidType(mat, 1);
1072   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1073   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1074   PetscCheckSameComm(mat, 1, viewer, 2);
1075   MatCheckPreallocated(mat, 1);
1076 
1077   PetscCall(PetscViewerGetFormat(viewer, &format));
1078   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1079   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1080 
1081   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1082   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1083   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1084   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");
1085 
1086   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1087   if (isascii) {
1088     PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix");
1089     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1090     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1091       MatNullSpace nullsp, transnullsp;
1092 
1093       PetscCall(PetscViewerASCIIPushTab(viewer));
1094       PetscCall(MatGetSize(mat, &rows, &cols));
1095       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1096       if (rbs != 1 || cbs != 1) {
1097         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1098         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1099       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1100       if (mat->factortype) {
1101         MatSolverType solver;
1102         PetscCall(MatFactorGetSolverType(mat, &solver));
1103         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1104       }
1105       if (mat->ops->getinfo) {
1106         MatInfo info;
1107         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1108         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1109         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1110       }
1111       PetscCall(MatGetNullSpace(mat, &nullsp));
1112       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1113       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1114       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1115       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1117       PetscCall(PetscViewerASCIIPushTab(viewer));
1118       PetscCall(MatProductView(mat, viewer));
1119       PetscCall(PetscViewerASCIIPopTab(viewer));
1120     }
1121   } else if (issaws) {
1122 #if defined(PETSC_HAVE_SAWS)
1123     PetscMPIInt rank;
1124 
1125     PetscCall(PetscObjectName((PetscObject)mat));
1126     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1127     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1128 #endif
1129   } else if (isstring) {
1130     const char *type;
1131     PetscCall(MatGetType(mat, &type));
1132     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1133     PetscTryTypeMethod(mat, view, viewer);
1134   }
1135   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1136     PetscCall(PetscViewerASCIIPushTab(viewer));
1137     PetscUseTypeMethod(mat, viewnative, viewer);
1138     PetscCall(PetscViewerASCIIPopTab(viewer));
1139   } else if (mat->ops->view) {
1140     PetscCall(PetscViewerASCIIPushTab(viewer));
1141     PetscUseTypeMethod(mat, view, viewer);
1142     PetscCall(PetscViewerASCIIPopTab(viewer));
1143   }
1144   if (isascii) {
1145     PetscCall(PetscViewerGetFormat(viewer, &format));
1146     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1147   }
1148   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1149   PetscFunctionReturn(0);
1150 }
1151 
1152 #if defined(PETSC_USE_DEBUG)
1153   #include <../src/sys/totalview/tv_data_display.h>
1154 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1155 {
1156   TV_add_row("Local rows", "int", &mat->rmap->n);
1157   TV_add_row("Local columns", "int", &mat->cmap->n);
1158   TV_add_row("Global rows", "int", &mat->rmap->N);
1159   TV_add_row("Global columns", "int", &mat->cmap->N);
1160   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1161   return TV_format_OK;
1162 }
1163 #endif
1164 
1165 /*@C
1166    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1167    with `MatView()`.  The matrix format is determined from the options database.
1168    Generates a parallel MPI matrix if the communicator has more than one
1169    processor.  The default matrix type is `MATAIJ`.
1170 
1171    Collective on mat
1172 
1173    Input Parameters:
1174 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1175             or some related function before a call to `MatLoad()`
1176 -  viewer - binary/HDF5 file viewer
1177 
1178    Options Database Keys:
1179    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1180    block size
1181 .    -matload_block_size <bs> - set block size
1182 
1183    Level: beginner
1184 
1185    Notes:
1186    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1187    `Mat` before calling this routine if you wish to set it from the options database.
1188 
1189    `MatLoad()` automatically loads into the options database any options
1190    given in the file filename.info where filename is the name of the file
1191    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1192    file will be ignored if you use the -viewer_binary_skip_info option.
1193 
1194    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1195    sets the default matrix type AIJ and sets the local and global sizes.
1196    If type and/or size is already set, then the same are used.
1197 
1198    In parallel, each processor can load a subset of rows (or the
1199    entire matrix).  This routine is especially useful when a large
1200    matrix is stored on disk and only part of it is desired on each
1201    processor.  For example, a parallel solver may access only some of
1202    the rows from each processor.  The algorithm used here reads
1203    relatively small blocks of data rather than reading the entire
1204    matrix and then subsetting it.
1205 
1206    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1207    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1208    or the sequence like
1209 .vb
1210     `PetscViewer` v;
1211     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1212     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1213     `PetscViewerSetFromOptions`(v);
1214     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1215     `PetscViewerFileSetName`(v,"datafile");
1216 .ve
1217    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1218 $ -viewer_type {binary,hdf5}
1219 
1220    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1221    and src/mat/tutorials/ex10.c with the second approach.
1222 
1223    Notes about the PETSc binary format:
1224    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1225    is read onto rank 0 and then shipped to its destination rank, one after another.
1226    Multiple objects, both matrices and vectors, can be stored within the same file.
1227    Their PetscObject name is ignored; they are loaded in the order of their storage.
1228 
1229    Most users should not need to know the details of the binary storage
1230    format, since `MatLoad()` and `MatView()` completely hide these details.
1231    But for anyone who's interested, the standard binary matrix storage
1232    format is
1233 
1234 $    PetscInt    MAT_FILE_CLASSID
1235 $    PetscInt    number of rows
1236 $    PetscInt    number of columns
1237 $    PetscInt    total number of nonzeros
1238 $    PetscInt    *number nonzeros in each row
1239 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1240 $    PetscScalar *values of all nonzeros
1241 
1242    PETSc automatically does the byte swapping for
1243 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1244 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1245 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1246 and `PetscBinaryWrite()` to see how this may be done.
1247 
1248    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1249    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1250    Each processor's chunk is loaded independently by its owning rank.
1251    Multiple objects, both matrices and vectors, can be stored within the same file.
1252    They are looked up by their PetscObject name.
1253 
1254    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1255    by default the same structure and naming of the AIJ arrays and column count
1256    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1257 $    save example.mat A b -v7.3
1258    can be directly read by this routine (see Reference 1 for details).
1259    Note that depending on your MATLAB version, this format might be a default,
1260    otherwise you can set it as default in Preferences.
1261 
1262    Unless -nocompression flag is used to save the file in MATLAB,
1263    PETSc must be configured with ZLIB package.
1264 
1265    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1266 
1267    Current HDF5 (MAT-File) limitations:
1268    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1269 
1270    Corresponding `MatView()` is not yet implemented.
1271 
1272    The loaded matrix is actually a transpose of the original one in MATLAB,
1273    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1274    With this format, matrix is automatically transposed by PETSc,
1275    unless the matrix is marked as SPD or symmetric
1276    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1277 
1278    References:
1279 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1280 
1281 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1282  @*/
1283 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1284 {
1285   PetscBool flg;
1286 
1287   PetscFunctionBegin;
1288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1289   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1290 
1291   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1292 
1293   flg = PETSC_FALSE;
1294   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1295   if (flg) {
1296     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1297     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1298   }
1299   flg = PETSC_FALSE;
1300   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1301   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1302 
1303   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1304   PetscUseTypeMethod(mat, load, viewer);
1305   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1306   PetscFunctionReturn(0);
1307 }
1308 
1309 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1310 {
1311   Mat_Redundant *redund = *redundant;
1312 
1313   PetscFunctionBegin;
1314   if (redund) {
1315     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1316       PetscCall(ISDestroy(&redund->isrow));
1317       PetscCall(ISDestroy(&redund->iscol));
1318       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1319     } else {
1320       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1321       PetscCall(PetscFree(redund->sbuf_j));
1322       PetscCall(PetscFree(redund->sbuf_a));
1323       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1324         PetscCall(PetscFree(redund->rbuf_j[i]));
1325         PetscCall(PetscFree(redund->rbuf_a[i]));
1326       }
1327       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1328     }
1329 
1330     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1331     PetscCall(PetscFree(redund));
1332   }
1333   PetscFunctionReturn(0);
1334 }
1335 
1336 /*@C
1337    MatDestroy - Frees space taken by a matrix.
1338 
1339    Collective on A
1340 
1341    Input Parameter:
1342 .  A - the matrix
1343 
1344    Level: beginner
1345 
1346    Developer Note:
1347    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1348    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1349    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1350    if changes are needed here.
1351 
1352 .seealso: `Mat`, `MatCreate()`
1353 @*/
1354 PetscErrorCode MatDestroy(Mat *A)
1355 {
1356   PetscFunctionBegin;
1357   if (!*A) PetscFunctionReturn(0);
1358   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1359   if (--((PetscObject)(*A))->refct > 0) {
1360     *A = NULL;
1361     PetscFunctionReturn(0);
1362   }
1363 
1364   /* if memory was published with SAWs then destroy it */
1365   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1366   PetscTryTypeMethod((*A), destroy);
1367 
1368   PetscCall(PetscFree((*A)->factorprefix));
1369   PetscCall(PetscFree((*A)->defaultvectype));
1370   PetscCall(PetscFree((*A)->defaultrandtype));
1371   PetscCall(PetscFree((*A)->bsizes));
1372   PetscCall(PetscFree((*A)->solvertype));
1373   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1374   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1375   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1376   PetscCall(MatProductClear(*A));
1377   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1378   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1379   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1380   PetscCall(MatDestroy(&(*A)->schur));
1381   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1382   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1383   PetscCall(PetscHeaderDestroy(A));
1384   PetscFunctionReturn(0);
1385 }
1386 
1387 /*@C
1388    MatSetValues - Inserts or adds a block of values into a matrix.
1389    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1390    MUST be called after all calls to `MatSetValues()` have been completed.
1391 
1392    Not Collective
1393 
1394    Input Parameters:
1395 +  mat - the matrix
1396 .  v - a logically two-dimensional array of values
1397 .  m, idxm - the number of rows and their global indices
1398 .  n, idxn - the number of columns and their global indices
1399 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1400 
1401    Notes:
1402    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1403       `MatSetUp()` before using this routine
1404 
1405    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1406 
1407    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1408    options cannot be mixed without intervening calls to the assembly
1409    routines.
1410 
1411    `MatSetValues()` uses 0-based row and column numbers in Fortran
1412    as well as in C.
1413 
1414    Negative indices may be passed in idxm and idxn, these rows and columns are
1415    simply ignored. This allows easily inserting element stiffness matrices
1416    with homogeneous Dirchlet boundary conditions that you don't want represented
1417    in the matrix.
1418 
1419    Efficiency Alert:
1420    The routine `MatSetValuesBlocked()` may offer much better efficiency
1421    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1422 
1423    Level: beginner
1424 
1425    Developer Note:
1426    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1427    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1428 
1429 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1430           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1431 @*/
1432 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1433 {
1434   PetscFunctionBeginHot;
1435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1436   PetscValidType(mat, 1);
1437   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1438   PetscValidIntPointer(idxm, 3);
1439   PetscValidIntPointer(idxn, 5);
1440   MatCheckPreallocated(mat, 1);
1441 
1442   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1443   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1444 
1445   if (PetscDefined(USE_DEBUG)) {
1446     PetscInt i, j;
1447 
1448     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1449     for (i = 0; i < m; i++) {
1450       for (j = 0; j < n; j++) {
1451         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1452 #if defined(PETSC_USE_COMPLEX)
1453           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1454 #else
1455           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1456 #endif
1457       }
1458     }
1459     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1460     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1461   }
1462 
1463   if (mat->assembled) {
1464     mat->was_assembled = PETSC_TRUE;
1465     mat->assembled     = PETSC_FALSE;
1466   }
1467   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1468   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1469   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1470   PetscFunctionReturn(0);
1471 }
1472 
1473 /*@C
1474    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1475    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1476    MUST be called after all calls to `MatSetValues()` have been completed.
1477 
1478    Not Collective
1479 
1480    Input Parameters:
1481 +  mat - the matrix
1482 .  v - a logically two-dimensional array of values
1483 .  ism - the rows to provide
1484 .  isn - the columns to provide
1485 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1486 
1487    Notes:
1488    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1489       `MatSetUp()` before using this routine
1490 
1491    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1492 
1493    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1494    options cannot be mixed without intervening calls to the assembly
1495    routines.
1496 
1497    MatSetValues() uses 0-based row and column numbers in Fortran
1498    as well as in C.
1499 
1500    Negative indices may be passed in ism and isn, these rows and columns are
1501    simply ignored. This allows easily inserting element stiffness matrices
1502    with homogeneous Dirchlet boundary conditions that you don't want represented
1503    in the matrix.
1504 
1505    Efficiency Alert:
1506    The routine `MatSetValuesBlocked()` may offer much better efficiency
1507    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1508 
1509    Level: beginner
1510 
1511    Developer Notes:
1512     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1513                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1514 
1515     This is currently not optimized for any particular `ISType`
1516 
1517 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1518           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1519 @*/
1520 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1521 {
1522   PetscInt        m, n;
1523   const PetscInt *rows, *cols;
1524 
1525   PetscFunctionBeginHot;
1526   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1527   PetscCall(ISGetIndices(ism, &rows));
1528   PetscCall(ISGetIndices(isn, &cols));
1529   PetscCall(ISGetLocalSize(ism, &m));
1530   PetscCall(ISGetLocalSize(isn, &n));
1531   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1532   PetscCall(ISRestoreIndices(ism, &rows));
1533   PetscCall(ISRestoreIndices(isn, &cols));
1534   PetscFunctionReturn(0);
1535 }
1536 
1537 /*@
1538    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1539         values into a matrix
1540 
1541    Not Collective
1542 
1543    Input Parameters:
1544 +  mat - the matrix
1545 .  row - the (block) row to set
1546 -  v - a logically two-dimensional array of values
1547 
1548    Notes:
1549    By the values, v, are column-oriented (for the block version) and sorted
1550 
1551    All the nonzeros in the row must be provided
1552 
1553    The matrix must have previously had its column indices set
1554 
1555    The row must belong to this process
1556 
1557    Level: intermediate
1558 
1559 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1560           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1561 @*/
1562 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1563 {
1564   PetscInt globalrow;
1565 
1566   PetscFunctionBegin;
1567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1568   PetscValidType(mat, 1);
1569   PetscValidScalarPointer(v, 3);
1570   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1571   PetscCall(MatSetValuesRow(mat, globalrow, v));
1572   PetscFunctionReturn(0);
1573 }
1574 
1575 /*@
1576    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1577         values into a matrix
1578 
1579    Not Collective
1580 
1581    Input Parameters:
1582 +  mat - the matrix
1583 .  row - the (block) row to set
1584 -  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
1585 
1586    Notes:
1587    The values, v, are column-oriented for the block version.
1588 
1589    All the nonzeros in the row must be provided
1590 
1591    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1592 
1593    The row must belong to this process
1594 
1595    Level: advanced
1596 
1597 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1598           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1599 @*/
1600 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1601 {
1602   PetscFunctionBeginHot;
1603   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1604   PetscValidType(mat, 1);
1605   MatCheckPreallocated(mat, 1);
1606   PetscValidScalarPointer(v, 3);
1607   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1608   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1609   mat->insertmode = INSERT_VALUES;
1610 
1611   if (mat->assembled) {
1612     mat->was_assembled = PETSC_TRUE;
1613     mat->assembled     = PETSC_FALSE;
1614   }
1615   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1616   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1617   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1618   PetscFunctionReturn(0);
1619 }
1620 
1621 /*@
1622    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1623      Using structured grid indexing
1624 
1625    Not Collective
1626 
1627    Input Parameters:
1628 +  mat - the matrix
1629 .  m - number of rows being entered
1630 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1631 .  n - number of columns being entered
1632 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1633 .  v - a logically two-dimensional array of values
1634 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1635 
1636    Notes:
1637    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1638 
1639    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1640    options cannot be mixed without intervening calls to the assembly
1641    routines.
1642 
1643    The grid coordinates are across the entire grid, not just the local portion
1644 
1645    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1646    as well as in C.
1647 
1648    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1649 
1650    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1651    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1652 
1653    The columns and rows in the stencil passed in MUST be contained within the
1654    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1655    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1656    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1657    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1658 
1659    In Fortran idxm and idxn should be declared as
1660 $     MatStencil idxm(4,m),idxn(4,n)
1661    and the values inserted using
1662 $    idxm(MatStencil_i,1) = i
1663 $    idxm(MatStencil_j,1) = j
1664 $    idxm(MatStencil_k,1) = k
1665 $    idxm(MatStencil_c,1) = c
1666    etc
1667 
1668    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1669    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1670    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1671    `DM_BOUNDARY_PERIODIC` boundary type.
1672 
1673    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
1674    a single value per point) you can skip filling those indices.
1675 
1676    Inspired by the structured grid interface to the HYPRE package
1677    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1678 
1679    Efficiency Alert:
1680    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1681    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1682 
1683    Level: beginner
1684 
1685 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1686           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1687 @*/
1688 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1689 {
1690   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1691   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1692   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1693 
1694   PetscFunctionBegin;
1695   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1696   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1697   PetscValidType(mat, 1);
1698   PetscValidPointer(idxm, 3);
1699   PetscValidPointer(idxn, 5);
1700 
1701   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1702     jdxm = buf;
1703     jdxn = buf + m;
1704   } else {
1705     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1706     jdxm = bufm;
1707     jdxn = bufn;
1708   }
1709   for (i = 0; i < m; i++) {
1710     for (j = 0; j < 3 - sdim; j++) dxm++;
1711     tmp = *dxm++ - starts[0];
1712     for (j = 0; j < dim - 1; j++) {
1713       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1714       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1715     }
1716     if (mat->stencil.noc) dxm++;
1717     jdxm[i] = tmp;
1718   }
1719   for (i = 0; i < n; i++) {
1720     for (j = 0; j < 3 - sdim; j++) dxn++;
1721     tmp = *dxn++ - starts[0];
1722     for (j = 0; j < dim - 1; j++) {
1723       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1724       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1725     }
1726     if (mat->stencil.noc) dxn++;
1727     jdxn[i] = tmp;
1728   }
1729   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1730   PetscCall(PetscFree2(bufm, bufn));
1731   PetscFunctionReturn(0);
1732 }
1733 
1734 /*@
1735    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1736      Using structured grid indexing
1737 
1738    Not Collective
1739 
1740    Input Parameters:
1741 +  mat - the matrix
1742 .  m - number of rows being entered
1743 .  idxm - grid coordinates for matrix rows being entered
1744 .  n - number of columns being entered
1745 .  idxn - grid coordinates for matrix columns being entered
1746 .  v - a logically two-dimensional array of values
1747 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1748 
1749    Notes:
1750    By default the values, v, are row-oriented and unsorted.
1751    See `MatSetOption()` for other options.
1752 
1753    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1754    options cannot be mixed without intervening calls to the assembly
1755    routines.
1756 
1757    The grid coordinates are across the entire grid, not just the local portion
1758 
1759    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1760    as well as in C.
1761 
1762    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1763 
1764    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1765    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1766 
1767    The columns and rows in the stencil passed in MUST be contained within the
1768    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1769    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1770    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1771    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1772 
1773    In Fortran idxm and idxn should be declared as
1774 $     MatStencil idxm(4,m),idxn(4,n)
1775    and the values inserted using
1776 $    idxm(MatStencil_i,1) = i
1777 $    idxm(MatStencil_j,1) = j
1778 $    idxm(MatStencil_k,1) = k
1779    etc
1780 
1781    Negative indices may be passed in idxm and idxn, these rows and columns are
1782    simply ignored. This allows easily inserting element stiffness matrices
1783    with homogeneous Dirchlet boundary conditions that you don't want represented
1784    in the matrix.
1785 
1786    Inspired by the structured grid interface to the HYPRE package
1787    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1788 
1789    Level: beginner
1790 
1791 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1792           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1793           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1794 @*/
1795 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1796 {
1797   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1798   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1799   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1800 
1801   PetscFunctionBegin;
1802   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1804   PetscValidType(mat, 1);
1805   PetscValidPointer(idxm, 3);
1806   PetscValidPointer(idxn, 5);
1807   PetscValidScalarPointer(v, 6);
1808 
1809   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1810     jdxm = buf;
1811     jdxn = buf + m;
1812   } else {
1813     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1814     jdxm = bufm;
1815     jdxn = bufn;
1816   }
1817   for (i = 0; i < m; i++) {
1818     for (j = 0; j < 3 - sdim; j++) dxm++;
1819     tmp = *dxm++ - starts[0];
1820     for (j = 0; j < sdim - 1; j++) {
1821       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1822       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1823     }
1824     dxm++;
1825     jdxm[i] = tmp;
1826   }
1827   for (i = 0; i < n; i++) {
1828     for (j = 0; j < 3 - sdim; j++) dxn++;
1829     tmp = *dxn++ - starts[0];
1830     for (j = 0; j < sdim - 1; j++) {
1831       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1832       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1833     }
1834     dxn++;
1835     jdxn[i] = tmp;
1836   }
1837   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1838   PetscCall(PetscFree2(bufm, bufn));
1839   PetscFunctionReturn(0);
1840 }
1841 
1842 /*@
1843    MatSetStencil - Sets the grid information for setting values into a matrix via
1844         `MatSetValuesStencil()`
1845 
1846    Not Collective
1847 
1848    Input Parameters:
1849 +  mat - the matrix
1850 .  dim - dimension of the grid 1, 2, or 3
1851 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1852 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1853 -  dof - number of degrees of freedom per node
1854 
1855    Notes:
1856    Inspired by the structured grid interface to the HYPRE package
1857    (www.llnl.gov/CASC/hyper)
1858 
1859    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1860    user.
1861 
1862    Level: beginner
1863 
1864 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1865           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1866 @*/
1867 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1868 {
1869   PetscFunctionBegin;
1870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1871   PetscValidIntPointer(dims, 3);
1872   PetscValidIntPointer(starts, 4);
1873 
1874   mat->stencil.dim = dim + (dof > 1);
1875   for (PetscInt i = 0; i < dim; i++) {
1876     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1877     mat->stencil.starts[i] = starts[dim - i - 1];
1878   }
1879   mat->stencil.dims[dim]   = dof;
1880   mat->stencil.starts[dim] = 0;
1881   mat->stencil.noc         = (PetscBool)(dof == 1);
1882   PetscFunctionReturn(0);
1883 }
1884 
1885 /*@C
1886    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1887 
1888    Not Collective
1889 
1890    Input Parameters:
1891 +  mat - the matrix
1892 .  v - a logically two-dimensional array of values
1893 .  m, idxm - the number of block rows and their global block indices
1894 .  n, idxn - the number of block columns and their global block indices
1895 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1896 
1897    Notes:
1898    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1899    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1900 
1901    The m and n count the NUMBER of blocks in the row direction and column direction,
1902    NOT the total number of rows/columns; for example, if the block size is 2 and
1903    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1904    The values in idxm would be 1 2; that is the first index for each block divided by
1905    the block size.
1906 
1907    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1908    preallocating it).
1909 
1910    By default the values, v, are row-oriented, so the layout of
1911    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1912 
1913    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1914    options cannot be mixed without intervening calls to the assembly
1915    routines.
1916 
1917    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1918    as well as in C.
1919 
1920    Negative indices may be passed in idxm and idxn, these rows and columns are
1921    simply ignored. This allows easily inserting element stiffness matrices
1922    with homogeneous Dirchlet boundary conditions that you don't want represented
1923    in the matrix.
1924 
1925    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1926    internal searching must be done to determine where to place the
1927    data in the matrix storage space.  By instead inserting blocks of
1928    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1929    reduced.
1930 
1931    Example:
1932 $   Suppose m=n=2 and block size(bs) = 2 The array is
1933 $
1934 $   1  2  | 3  4
1935 $   5  6  | 7  8
1936 $   - - - | - - -
1937 $   9  10 | 11 12
1938 $   13 14 | 15 16
1939 $
1940 $   v[] should be passed in like
1941 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1942 $
1943 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1944 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1945 
1946    Level: intermediate
1947 
1948 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1949 @*/
1950 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1951 {
1952   PetscFunctionBeginHot;
1953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1954   PetscValidType(mat, 1);
1955   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1956   PetscValidIntPointer(idxm, 3);
1957   PetscValidIntPointer(idxn, 5);
1958   MatCheckPreallocated(mat, 1);
1959   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1960   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1961   if (PetscDefined(USE_DEBUG)) {
1962     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1963     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1964   }
1965   if (PetscDefined(USE_DEBUG)) {
1966     PetscInt rbs, cbs, M, N, i;
1967     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1968     PetscCall(MatGetSize(mat, &M, &N));
1969     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);
1970     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);
1971   }
1972   if (mat->assembled) {
1973     mat->was_assembled = PETSC_TRUE;
1974     mat->assembled     = PETSC_FALSE;
1975   }
1976   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1977   if (mat->ops->setvaluesblocked) {
1978     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1979   } else {
1980     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1981     PetscInt i, j, bs, cbs;
1982 
1983     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1984     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1985       iidxm = buf;
1986       iidxn = buf + m * bs;
1987     } else {
1988       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1989       iidxm = bufr;
1990       iidxn = bufc;
1991     }
1992     for (i = 0; i < m; i++) {
1993       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1994     }
1995     if (m != n || bs != cbs || idxm != idxn) {
1996       for (i = 0; i < n; i++) {
1997         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1998       }
1999     } else iidxn = iidxm;
2000     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2001     PetscCall(PetscFree2(bufr, bufc));
2002   }
2003   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2004   PetscFunctionReturn(0);
2005 }
2006 
2007 /*@C
2008    MatGetValues - Gets a block of local values from a matrix.
2009 
2010    Not Collective; can only return values that are owned by the give process
2011 
2012    Input Parameters:
2013 +  mat - the matrix
2014 .  v - a logically two-dimensional array for storing the values
2015 .  m, idxm - the number of rows and their global indices
2016 -  n, idxn - the number of columns and their global indices
2017 
2018    Notes:
2019      The user must allocate space (m*n `PetscScalar`s) for the values, v.
2020      The values, v, are then returned in a row-oriented format,
2021      analogous to that used by default in `MatSetValues()`.
2022 
2023      `MatGetValues()` uses 0-based row and column numbers in
2024      Fortran as well as in C.
2025 
2026      `MatGetValues()` requires that the matrix has been assembled
2027      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2028      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2029      without intermediate matrix assembly.
2030 
2031      Negative row or column indices will be ignored and those locations in v[] will be
2032      left unchanged.
2033 
2034      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2035      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2036      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2037 
2038    Level: advanced
2039 
2040 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2041 @*/
2042 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2043 {
2044   PetscFunctionBegin;
2045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2046   PetscValidType(mat, 1);
2047   if (!m || !n) PetscFunctionReturn(0);
2048   PetscValidIntPointer(idxm, 3);
2049   PetscValidIntPointer(idxn, 5);
2050   PetscValidScalarPointer(v, 6);
2051   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2052   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2053   MatCheckPreallocated(mat, 1);
2054 
2055   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2056   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2057   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2058   PetscFunctionReturn(0);
2059 }
2060 
2061 /*@C
2062    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2063      defined previously by `MatSetLocalToGlobalMapping()`
2064 
2065    Not Collective
2066 
2067    Input Parameters:
2068 +  mat - the matrix
2069 .  nrow, irow - number of rows and their local indices
2070 -  ncol, icol - number of columns and their local indices
2071 
2072    Output Parameter:
2073 .  y -  a logically two-dimensional array of values
2074 
2075    Notes:
2076      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2077 
2078      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,
2079      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2080      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2081      with `MatSetLocalToGlobalMapping()`.
2082 
2083    Developer Note:
2084       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2085       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2086 
2087    Level: advanced
2088 
2089 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2090           `MatSetValuesLocal()`, `MatGetValues()`
2091 @*/
2092 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2093 {
2094   PetscFunctionBeginHot;
2095   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2096   PetscValidType(mat, 1);
2097   MatCheckPreallocated(mat, 1);
2098   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2099   PetscValidIntPointer(irow, 3);
2100   PetscValidIntPointer(icol, 5);
2101   if (PetscDefined(USE_DEBUG)) {
2102     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2103     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2104   }
2105   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2106   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2107   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2108   else {
2109     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2110     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2111       irowm = buf;
2112       icolm = buf + nrow;
2113     } else {
2114       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2115       irowm = bufr;
2116       icolm = bufc;
2117     }
2118     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2119     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2120     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2121     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2122     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2123     PetscCall(PetscFree2(bufr, bufc));
2124   }
2125   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2126   PetscFunctionReturn(0);
2127 }
2128 
2129 /*@
2130   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2131   the same size. Currently, this can only be called once and creates the given matrix.
2132 
2133   Not Collective
2134 
2135   Input Parameters:
2136 + mat - the matrix
2137 . nb - the number of blocks
2138 . bs - the number of rows (and columns) in each block
2139 . rows - a concatenation of the rows for each block
2140 - v - a concatenation of logically two-dimensional arrays of values
2141 
2142   Note:
2143   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2144 
2145   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2146 
2147   Level: advanced
2148 
2149 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2150           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2151 @*/
2152 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2153 {
2154   PetscFunctionBegin;
2155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2156   PetscValidType(mat, 1);
2157   PetscValidIntPointer(rows, 4);
2158   PetscValidScalarPointer(v, 5);
2159   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2160 
2161   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2162   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2163   else {
2164     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2165   }
2166   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2167   PetscFunctionReturn(0);
2168 }
2169 
2170 /*@
2171    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2172    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2173    using a local (per-processor) numbering.
2174 
2175    Not Collective
2176 
2177    Input Parameters:
2178 +  x - the matrix
2179 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2180 -  cmapping - column mapping
2181 
2182    Level: intermediate
2183 
2184    Note:
2185    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2186 
2187 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2188 @*/
2189 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2190 {
2191   PetscFunctionBegin;
2192   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2193   PetscValidType(x, 1);
2194   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2195   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2196   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2197   else {
2198     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2199     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2200   }
2201   PetscFunctionReturn(0);
2202 }
2203 
2204 /*@
2205    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2206 
2207    Not Collective
2208 
2209    Input Parameter:
2210 .  A - the matrix
2211 
2212    Output Parameters:
2213 + rmapping - row mapping
2214 - cmapping - column mapping
2215 
2216    Level: advanced
2217 
2218 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2219 @*/
2220 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2221 {
2222   PetscFunctionBegin;
2223   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2224   PetscValidType(A, 1);
2225   if (rmapping) {
2226     PetscValidPointer(rmapping, 2);
2227     *rmapping = A->rmap->mapping;
2228   }
2229   if (cmapping) {
2230     PetscValidPointer(cmapping, 3);
2231     *cmapping = A->cmap->mapping;
2232   }
2233   PetscFunctionReturn(0);
2234 }
2235 
2236 /*@
2237    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2238 
2239    Logically Collective on A
2240 
2241    Input Parameters:
2242 +  A - the matrix
2243 . rmap - row layout
2244 - cmap - column layout
2245 
2246    Level: advanced
2247 
2248    Note:
2249    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2250 
2251 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2252 @*/
2253 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2254 {
2255   PetscFunctionBegin;
2256   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2257   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2258   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2259   PetscFunctionReturn(0);
2260 }
2261 
2262 /*@
2263    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2264 
2265    Not Collective
2266 
2267    Input Parameter:
2268 .  A - the matrix
2269 
2270    Output Parameters:
2271 + rmap - row layout
2272 - cmap - column layout
2273 
2274    Level: advanced
2275 
2276 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2277 @*/
2278 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2279 {
2280   PetscFunctionBegin;
2281   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2282   PetscValidType(A, 1);
2283   if (rmap) {
2284     PetscValidPointer(rmap, 2);
2285     *rmap = A->rmap;
2286   }
2287   if (cmap) {
2288     PetscValidPointer(cmap, 3);
2289     *cmap = A->cmap;
2290   }
2291   PetscFunctionReturn(0);
2292 }
2293 
2294 /*@C
2295    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2296    using a local numbering of the nodes.
2297 
2298    Not Collective
2299 
2300    Input Parameters:
2301 +  mat - the matrix
2302 .  nrow, irow - number of rows and their local indices
2303 .  ncol, icol - number of columns and their local indices
2304 .  y -  a logically two-dimensional array of values
2305 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2306 
2307    Notes:
2308    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2309       `MatSetUp()` before using this routine
2310 
2311    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2312 
2313    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2314    options cannot be mixed without intervening calls to the assembly
2315    routines.
2316 
2317    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2318    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2319 
2320    Level: intermediate
2321 
2322    Developer Note:
2323     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2324                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2325 
2326 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2327           `MatGetValuesLocal()`
2328 @*/
2329 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2330 {
2331   PetscFunctionBeginHot;
2332   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2333   PetscValidType(mat, 1);
2334   MatCheckPreallocated(mat, 1);
2335   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2336   PetscValidIntPointer(irow, 3);
2337   PetscValidIntPointer(icol, 5);
2338   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2339   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2340   if (PetscDefined(USE_DEBUG)) {
2341     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2342     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2343   }
2344 
2345   if (mat->assembled) {
2346     mat->was_assembled = PETSC_TRUE;
2347     mat->assembled     = PETSC_FALSE;
2348   }
2349   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2350   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2351   else {
2352     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2353     const PetscInt *irowm, *icolm;
2354 
2355     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2356       bufr  = buf;
2357       bufc  = buf + nrow;
2358       irowm = bufr;
2359       icolm = bufc;
2360     } else {
2361       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2362       irowm = bufr;
2363       icolm = bufc;
2364     }
2365     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2366     else irowm = irow;
2367     if (mat->cmap->mapping) {
2368       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2369         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2370       } else icolm = irowm;
2371     } else icolm = icol;
2372     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2373     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2374   }
2375   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2376   PetscFunctionReturn(0);
2377 }
2378 
2379 /*@C
2380    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2381    using a local ordering of the nodes a block at a time.
2382 
2383    Not Collective
2384 
2385    Input Parameters:
2386 +  x - the matrix
2387 .  nrow, irow - number of rows and their local indices
2388 .  ncol, icol - number of columns and their local indices
2389 .  y -  a logically two-dimensional array of values
2390 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2391 
2392    Notes:
2393    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2394       `MatSetUp()` before using this routine
2395 
2396    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2397       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2398 
2399    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2400    options cannot be mixed without intervening calls to the assembly
2401    routines.
2402 
2403    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2404    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2405 
2406    Level: intermediate
2407 
2408    Developer Note:
2409     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2410                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2411 
2412 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2413           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2414 @*/
2415 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2416 {
2417   PetscFunctionBeginHot;
2418   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2419   PetscValidType(mat, 1);
2420   MatCheckPreallocated(mat, 1);
2421   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2422   PetscValidIntPointer(irow, 3);
2423   PetscValidIntPointer(icol, 5);
2424   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2425   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2426   if (PetscDefined(USE_DEBUG)) {
2427     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2428     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);
2429   }
2430 
2431   if (mat->assembled) {
2432     mat->was_assembled = PETSC_TRUE;
2433     mat->assembled     = PETSC_FALSE;
2434   }
2435   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2436     PetscInt irbs, rbs;
2437     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2438     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2439     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2440   }
2441   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2442     PetscInt icbs, cbs;
2443     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2444     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2445     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2446   }
2447   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2448   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2449   else {
2450     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2451     const PetscInt *irowm, *icolm;
2452 
2453     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2454       bufr  = buf;
2455       bufc  = buf + nrow;
2456       irowm = bufr;
2457       icolm = bufc;
2458     } else {
2459       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2460       irowm = bufr;
2461       icolm = bufc;
2462     }
2463     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2464     else irowm = irow;
2465     if (mat->cmap->mapping) {
2466       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2467         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2468       } else icolm = irowm;
2469     } else icolm = icol;
2470     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2471     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2472   }
2473   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2474   PetscFunctionReturn(0);
2475 }
2476 
2477 /*@
2478    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2479 
2480    Collective on mat
2481 
2482    Input Parameters:
2483 +  mat - the matrix
2484 -  x   - the vector to be multiplied
2485 
2486    Output Parameters:
2487 .  y - the result
2488 
2489    Note:
2490    The vectors x and y cannot be the same.  I.e., one cannot
2491    call `MatMultDiagonalBlock`(A,y,y).
2492 
2493    Level: developer
2494 
2495 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2496 @*/
2497 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2498 {
2499   PetscFunctionBegin;
2500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2501   PetscValidType(mat, 1);
2502   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2503   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2504 
2505   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2506   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2507   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2508   MatCheckPreallocated(mat, 1);
2509 
2510   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2511   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2512   PetscFunctionReturn(0);
2513 }
2514 
2515 /* --------------------------------------------------------*/
2516 /*@
2517    MatMult - Computes the matrix-vector product, y = Ax.
2518 
2519    Neighbor-wise Collective on mat
2520 
2521    Input Parameters:
2522 +  mat - the matrix
2523 -  x   - the vector to be multiplied
2524 
2525    Output Parameters:
2526 .  y - the result
2527 
2528    Note:
2529    The vectors x and y cannot be the same.  I.e., one cannot
2530    call `MatMult`(A,y,y).
2531 
2532    Level: beginner
2533 
2534 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2535 @*/
2536 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2537 {
2538   PetscFunctionBegin;
2539   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2540   PetscValidType(mat, 1);
2541   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2542   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2543   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2544   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2545   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2546   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);
2547   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);
2548   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);
2549   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);
2550   PetscCall(VecSetErrorIfLocked(y, 3));
2551   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2552   MatCheckPreallocated(mat, 1);
2553 
2554   PetscCall(VecLockReadPush(x));
2555   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2556   PetscUseTypeMethod(mat, mult, x, y);
2557   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2558   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2559   PetscCall(VecLockReadPop(x));
2560   PetscFunctionReturn(0);
2561 }
2562 
2563 /*@
2564    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2565 
2566    Neighbor-wise Collective on mat
2567 
2568    Input Parameters:
2569 +  mat - the matrix
2570 -  x   - the vector to be multiplied
2571 
2572    Output Parameters:
2573 .  y - the result
2574 
2575    Notes:
2576    The vectors x and y cannot be the same.  I.e., one cannot
2577    call `MatMultTranspose`(A,y,y).
2578 
2579    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2580    use `MatMultHermitianTranspose()`
2581 
2582    Level: beginner
2583 
2584 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2585 @*/
2586 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2587 {
2588   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2589 
2590   PetscFunctionBegin;
2591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2592   PetscValidType(mat, 1);
2593   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2594   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2595 
2596   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2597   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2598   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2599   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);
2600   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);
2601   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);
2602   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);
2603   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2604   MatCheckPreallocated(mat, 1);
2605 
2606   if (!mat->ops->multtranspose) {
2607     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2608     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);
2609   } else op = mat->ops->multtranspose;
2610   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2611   PetscCall(VecLockReadPush(x));
2612   PetscCall((*op)(mat, x, y));
2613   PetscCall(VecLockReadPop(x));
2614   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2615   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2616   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2617   PetscFunctionReturn(0);
2618 }
2619 
2620 /*@
2621    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2622 
2623    Neighbor-wise Collective on mat
2624 
2625    Input Parameters:
2626 +  mat - the matrix
2627 -  x   - the vector to be multilplied
2628 
2629    Output Parameters:
2630 .  y - the result
2631 
2632    Notes:
2633    The vectors x and y cannot be the same.  I.e., one cannot
2634    call `MatMultHermitianTranspose`(A,y,y).
2635 
2636    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2637 
2638    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2639 
2640    Level: beginner
2641 
2642 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2643 @*/
2644 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2645 {
2646   PetscFunctionBegin;
2647   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2648   PetscValidType(mat, 1);
2649   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2650   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2651 
2652   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2653   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2654   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2655   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);
2656   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);
2657   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);
2658   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);
2659   MatCheckPreallocated(mat, 1);
2660 
2661   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2662 #if defined(PETSC_USE_COMPLEX)
2663   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2664     PetscCall(VecLockReadPush(x));
2665     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2666     else PetscUseTypeMethod(mat, mult, x, y);
2667     PetscCall(VecLockReadPop(x));
2668   } else {
2669     Vec w;
2670     PetscCall(VecDuplicate(x, &w));
2671     PetscCall(VecCopy(x, w));
2672     PetscCall(VecConjugate(w));
2673     PetscCall(MatMultTranspose(mat, w, y));
2674     PetscCall(VecDestroy(&w));
2675     PetscCall(VecConjugate(y));
2676   }
2677   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2678 #else
2679   PetscCall(MatMultTranspose(mat, x, y));
2680 #endif
2681   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2682   PetscFunctionReturn(0);
2683 }
2684 
2685 /*@
2686     MatMultAdd -  Computes v3 = v2 + A * v1.
2687 
2688     Neighbor-wise Collective on mat
2689 
2690     Input Parameters:
2691 +   mat - the matrix
2692 -   v1, v2 - the vectors
2693 
2694     Output Parameters:
2695 .   v3 - the result
2696 
2697     Note:
2698     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2699     call `MatMultAdd`(A,v1,v2,v1).
2700 
2701     Level: beginner
2702 
2703 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2704 @*/
2705 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2706 {
2707   PetscFunctionBegin;
2708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2709   PetscValidType(mat, 1);
2710   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2711   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2712   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2713 
2714   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2715   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2716   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);
2717   /* 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);
2718      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); */
2719   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);
2720   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);
2721   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2722   MatCheckPreallocated(mat, 1);
2723 
2724   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2725   PetscCall(VecLockReadPush(v1));
2726   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2727   PetscCall(VecLockReadPop(v1));
2728   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2729   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2730   PetscFunctionReturn(0);
2731 }
2732 
2733 /*@
2734    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2735 
2736    Neighbor-wise Collective on mat
2737 
2738    Input Parameters:
2739 +  mat - the matrix
2740 -  v1, v2 - the vectors
2741 
2742    Output Parameters:
2743 .  v3 - the result
2744 
2745    Note:
2746    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2747    call `MatMultTransposeAdd`(A,v1,v2,v1).
2748 
2749    Level: beginner
2750 
2751 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2752 @*/
2753 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2754 {
2755   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2756 
2757   PetscFunctionBegin;
2758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2759   PetscValidType(mat, 1);
2760   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2761   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2762   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2763 
2764   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2765   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2766   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);
2767   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);
2768   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);
2769   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2770   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2771   MatCheckPreallocated(mat, 1);
2772 
2773   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2774   PetscCall(VecLockReadPush(v1));
2775   PetscCall((*op)(mat, v1, v2, v3));
2776   PetscCall(VecLockReadPop(v1));
2777   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2778   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2779   PetscFunctionReturn(0);
2780 }
2781 
2782 /*@
2783    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2784 
2785    Neighbor-wise Collective on mat
2786 
2787    Input Parameters:
2788 +  mat - the matrix
2789 -  v1, v2 - the vectors
2790 
2791    Output Parameters:
2792 .  v3 - the result
2793 
2794    Note:
2795    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2796    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2797 
2798    Level: beginner
2799 
2800 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2801 @*/
2802 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2803 {
2804   PetscFunctionBegin;
2805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2806   PetscValidType(mat, 1);
2807   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2808   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2809   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2810 
2811   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2812   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2813   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2814   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);
2815   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);
2816   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);
2817   MatCheckPreallocated(mat, 1);
2818 
2819   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2820   PetscCall(VecLockReadPush(v1));
2821   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2822   else {
2823     Vec w, z;
2824     PetscCall(VecDuplicate(v1, &w));
2825     PetscCall(VecCopy(v1, w));
2826     PetscCall(VecConjugate(w));
2827     PetscCall(VecDuplicate(v3, &z));
2828     PetscCall(MatMultTranspose(mat, w, z));
2829     PetscCall(VecDestroy(&w));
2830     PetscCall(VecConjugate(z));
2831     if (v2 != v3) {
2832       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2833     } else {
2834       PetscCall(VecAXPY(v3, 1.0, z));
2835     }
2836     PetscCall(VecDestroy(&z));
2837   }
2838   PetscCall(VecLockReadPop(v1));
2839   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2840   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2841   PetscFunctionReturn(0);
2842 }
2843 
2844 /*@C
2845    MatGetFactorType - gets the type of factorization it is
2846 
2847    Not Collective
2848 
2849    Input Parameters:
2850 .  mat - the matrix
2851 
2852    Output Parameters:
2853 .  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`
2854 
2855    Level: intermediate
2856 
2857 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2858           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2859 @*/
2860 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2861 {
2862   PetscFunctionBegin;
2863   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2864   PetscValidType(mat, 1);
2865   PetscValidPointer(t, 2);
2866   *t = mat->factortype;
2867   PetscFunctionReturn(0);
2868 }
2869 
2870 /*@C
2871    MatSetFactorType - sets the type of factorization it is
2872 
2873    Logically Collective on mat
2874 
2875    Input Parameters:
2876 +  mat - the matrix
2877 -  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`
2878 
2879    Level: intermediate
2880 
2881 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2882           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2883 @*/
2884 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2885 {
2886   PetscFunctionBegin;
2887   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2888   PetscValidType(mat, 1);
2889   mat->factortype = t;
2890   PetscFunctionReturn(0);
2891 }
2892 
2893 /* ------------------------------------------------------------*/
2894 /*@C
2895    MatGetInfo - Returns information about matrix storage (number of
2896    nonzeros, memory, etc.).
2897 
2898    Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2899 
2900    Input Parameter:
2901 .  mat - the matrix
2902 
2903    Output Parameters:
2904 +  flag - flag indicating the type of parameters to be returned
2905    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2906    MAT_GLOBAL_SUM - sum over all processors)
2907 -  info - matrix information context
2908 
2909    Notes:
2910    The `MatInfo` context contains a variety of matrix data, including
2911    number of nonzeros allocated and used, number of mallocs during
2912    matrix assembly, etc.  Additional information for factored matrices
2913    is provided (such as the fill ratio, number of mallocs during
2914    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2915    when using the runtime options
2916 $       -info -mat_view ::ascii_info
2917 
2918    Example for C/C++ Users:
2919    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2920    data within the MatInfo context.  For example,
2921 .vb
2922       MatInfo info;
2923       Mat     A;
2924       double  mal, nz_a, nz_u;
2925 
2926       MatGetInfo(A,MAT_LOCAL,&info);
2927       mal  = info.mallocs;
2928       nz_a = info.nz_allocated;
2929 .ve
2930 
2931    Example for Fortran Users:
2932    Fortran users should declare info as a double precision
2933    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2934    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2935    a complete list of parameter names.
2936 .vb
2937       double  precision info(MAT_INFO_SIZE)
2938       double  precision mal, nz_a
2939       Mat     A
2940       integer ierr
2941 
2942       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2943       mal = info(MAT_INFO_MALLOCS)
2944       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2945 .ve
2946 
2947     Level: intermediate
2948 
2949     Developer Note: fortran interface is not autogenerated as the f90
2950     interface definition cannot be generated correctly [due to MatInfo]
2951 
2952 .seealso: `MatInfo`, `MatStashGetInfo()`
2953 @*/
2954 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2955 {
2956   PetscFunctionBegin;
2957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2958   PetscValidType(mat, 1);
2959   PetscValidPointer(info, 3);
2960   MatCheckPreallocated(mat, 1);
2961   PetscUseTypeMethod(mat, getinfo, flag, info);
2962   PetscFunctionReturn(0);
2963 }
2964 
2965 /*
2966    This is used by external packages where it is not easy to get the info from the actual
2967    matrix factorization.
2968 */
2969 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2970 {
2971   PetscFunctionBegin;
2972   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2973   PetscFunctionReturn(0);
2974 }
2975 
2976 /* ----------------------------------------------------------*/
2977 
2978 /*@C
2979    MatLUFactor - Performs in-place LU factorization of matrix.
2980 
2981    Collective on mat
2982 
2983    Input Parameters:
2984 +  mat - the matrix
2985 .  row - row permutation
2986 .  col - column permutation
2987 -  info - options for factorization, includes
2988 $          fill - expected fill as ratio of original fill.
2989 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2990 $                   Run with the option -info to determine an optimal value to use
2991 
2992    Notes:
2993    Most users should employ the `KSP` interface for linear solvers
2994    instead of working directly with matrix algebra routines such as this.
2995    See, e.g., `KSPCreate()`.
2996 
2997    This changes the state of the matrix to a factored matrix; it cannot be used
2998    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2999 
3000    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3001    when not using `KSP`.
3002 
3003    Level: developer
3004 
3005    Developer Note:
3006    The Fortran interface is not autogenerated as the f90
3007    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3008 
3009 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3010           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3011 @*/
3012 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3013 {
3014   MatFactorInfo tinfo;
3015 
3016   PetscFunctionBegin;
3017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3018   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3019   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3020   if (info) PetscValidPointer(info, 4);
3021   PetscValidType(mat, 1);
3022   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3023   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3024   MatCheckPreallocated(mat, 1);
3025   if (!info) {
3026     PetscCall(MatFactorInfoInitialize(&tinfo));
3027     info = &tinfo;
3028   }
3029 
3030   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3031   PetscUseTypeMethod(mat, lufactor, row, col, info);
3032   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3033   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3034   PetscFunctionReturn(0);
3035 }
3036 
3037 /*@C
3038    MatILUFactor - Performs in-place ILU factorization of matrix.
3039 
3040    Collective on mat
3041 
3042    Input Parameters:
3043 +  mat - the matrix
3044 .  row - row permutation
3045 .  col - column permutation
3046 -  info - structure containing
3047 $      levels - number of levels of fill.
3048 $      expected fill - as ratio of original fill.
3049 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3050                 missing diagonal entries)
3051 
3052    Notes:
3053    Most users should employ the `KSP` interface for linear solvers
3054    instead of working directly with matrix algebra routines such as this.
3055    See, e.g., `KSPCreate()`.
3056 
3057    Probably really in-place only when level of fill is zero, otherwise allocates
3058    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3059    when not using `KSP`.
3060 
3061    Level: developer
3062 
3063    Developer Note:
3064    The Fortran interface is not autogenerated as the f90
3065    interface definition cannot be generated correctly [due to MatFactorInfo]
3066 
3067 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3068 @*/
3069 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3070 {
3071   PetscFunctionBegin;
3072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3073   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3074   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3075   PetscValidPointer(info, 4);
3076   PetscValidType(mat, 1);
3077   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3078   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3079   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3080   MatCheckPreallocated(mat, 1);
3081 
3082   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3083   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3084   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3085   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3086   PetscFunctionReturn(0);
3087 }
3088 
3089 /*@C
3090    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3091    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3092 
3093    Collective on fact
3094 
3095    Input Parameters:
3096 +  fact - the factor matrix obtained with `MatGetFactor()`
3097 .  mat - the matrix
3098 .  row, col - row and column permutations
3099 -  info - options for factorization, includes
3100 .vb
3101           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3102           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3103 .ve
3104 
3105    Notes:
3106     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3107 
3108    Most users should employ the simplified `KSP` interface for linear solvers
3109    instead of working directly with matrix algebra routines such as this.
3110    See, e.g., `KSPCreate()`.
3111 
3112    Level: developer
3113 
3114    Developer Note:
3115    The Fortran interface is not autogenerated as the f90
3116    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3117 
3118 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3119 @*/
3120 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3121 {
3122   MatFactorInfo tinfo;
3123 
3124   PetscFunctionBegin;
3125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3126   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3127   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3128   if (info) PetscValidPointer(info, 5);
3129   PetscValidType(mat, 2);
3130   PetscValidPointer(fact, 1);
3131   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3132   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3133   if (!(fact)->ops->lufactorsymbolic) {
3134     MatSolverType stype;
3135     PetscCall(MatFactorGetSolverType(fact, &stype));
3136     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3137   }
3138   MatCheckPreallocated(mat, 2);
3139   if (!info) {
3140     PetscCall(MatFactorInfoInitialize(&tinfo));
3141     info = &tinfo;
3142   }
3143 
3144   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3145   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3146   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3147   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3148   PetscFunctionReturn(0);
3149 }
3150 
3151 /*@C
3152    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3153    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3154 
3155    Collective on fact
3156 
3157    Input Parameters:
3158 +  fact - the factor matrix obtained with `MatGetFactor()`
3159 .  mat - the matrix
3160 -  info - options for factorization
3161 
3162    Notes:
3163    See `MatLUFactor()` for in-place factorization.  See
3164    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3165 
3166    Most users should employ the `KSP` interface for linear solvers
3167    instead of working directly with matrix algebra routines such as this.
3168    See, e.g., `KSPCreate()`.
3169 
3170    Level: developer
3171 
3172     Developer Note:
3173     The Fortran interface is not autogenerated as the f90
3174     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3175 
3176 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3177 @*/
3178 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3179 {
3180   MatFactorInfo tinfo;
3181 
3182   PetscFunctionBegin;
3183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3184   PetscValidType(mat, 2);
3185   PetscValidPointer(fact, 1);
3186   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3187   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3188   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,
3189              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3190 
3191   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3192   MatCheckPreallocated(mat, 2);
3193   if (!info) {
3194     PetscCall(MatFactorInfoInitialize(&tinfo));
3195     info = &tinfo;
3196   }
3197 
3198   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3199   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3200   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3201   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3202   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3203   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3204   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3205   PetscFunctionReturn(0);
3206 }
3207 
3208 /*@C
3209    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3210    symmetric matrix.
3211 
3212    Collective on mat
3213 
3214    Input Parameters:
3215 +  mat - the matrix
3216 .  perm - row and column permutations
3217 -  f - expected fill as ratio of original fill
3218 
3219    Notes:
3220    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3221    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3222 
3223    Most users should employ the `KSP` interface for linear solvers
3224    instead of working directly with matrix algebra routines such as this.
3225    See, e.g., `KSPCreate()`.
3226 
3227    Level: developer
3228 
3229    Developer Note:
3230    The Fortran interface is not autogenerated as the f90
3231    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3232 
3233 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3234           `MatGetOrdering()`
3235 @*/
3236 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3237 {
3238   MatFactorInfo tinfo;
3239 
3240   PetscFunctionBegin;
3241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3242   PetscValidType(mat, 1);
3243   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3244   if (info) PetscValidPointer(info, 3);
3245   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3246   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3247   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3248   MatCheckPreallocated(mat, 1);
3249   if (!info) {
3250     PetscCall(MatFactorInfoInitialize(&tinfo));
3251     info = &tinfo;
3252   }
3253 
3254   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3255   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3256   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3257   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3258   PetscFunctionReturn(0);
3259 }
3260 
3261 /*@C
3262    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3263    of a symmetric matrix.
3264 
3265    Collective on fact
3266 
3267    Input Parameters:
3268 +  fact - the factor matrix obtained with `MatGetFactor()`
3269 .  mat - the matrix
3270 .  perm - row and column permutations
3271 -  info - options for factorization, includes
3272 $          fill - expected fill as ratio of original fill.
3273 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3274 $                   Run with the option -info to determine an optimal value to use
3275 
3276    Notes:
3277    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3278    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3279 
3280    Most users should employ the `KSP` interface for linear solvers
3281    instead of working directly with matrix algebra routines such as this.
3282    See, e.g., `KSPCreate()`.
3283 
3284    Level: developer
3285 
3286    Developer Note:
3287    The Fortran interface is not autogenerated as the f90
3288    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3289 
3290 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3291           `MatGetOrdering()`
3292 @*/
3293 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3294 {
3295   MatFactorInfo tinfo;
3296 
3297   PetscFunctionBegin;
3298   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3299   PetscValidType(mat, 2);
3300   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3301   if (info) PetscValidPointer(info, 4);
3302   PetscValidPointer(fact, 1);
3303   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3304   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3305   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3306   if (!(fact)->ops->choleskyfactorsymbolic) {
3307     MatSolverType stype;
3308     PetscCall(MatFactorGetSolverType(fact, &stype));
3309     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3310   }
3311   MatCheckPreallocated(mat, 2);
3312   if (!info) {
3313     PetscCall(MatFactorInfoInitialize(&tinfo));
3314     info = &tinfo;
3315   }
3316 
3317   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3318   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3319   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3320   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3321   PetscFunctionReturn(0);
3322 }
3323 
3324 /*@C
3325    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3326    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3327    `MatCholeskyFactorSymbolic()`.
3328 
3329    Collective on fact
3330 
3331    Input Parameters:
3332 +  fact - the factor matrix obtained with `MatGetFactor()`
3333 .  mat - the initial matrix
3334 .  info - options for factorization
3335 -  fact - the symbolic factor of mat
3336 
3337    Note:
3338    Most users should employ the `KSP` interface for linear solvers
3339    instead of working directly with matrix algebra routines such as this.
3340    See, e.g., `KSPCreate()`.
3341 
3342    Level: developer
3343 
3344    Developer Note:
3345    The Fortran interface is not autogenerated as the f90
3346    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3347 
3348 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3349 @*/
3350 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3351 {
3352   MatFactorInfo tinfo;
3353 
3354   PetscFunctionBegin;
3355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3356   PetscValidType(mat, 2);
3357   PetscValidPointer(fact, 1);
3358   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3359   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3360   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3361   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,
3362              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3363   MatCheckPreallocated(mat, 2);
3364   if (!info) {
3365     PetscCall(MatFactorInfoInitialize(&tinfo));
3366     info = &tinfo;
3367   }
3368 
3369   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3370   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3371   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3372   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3373   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3374   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3375   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3376   PetscFunctionReturn(0);
3377 }
3378 
3379 /*@
3380    MatQRFactor - Performs in-place QR factorization of matrix.
3381 
3382    Collective on mat
3383 
3384    Input Parameters:
3385 +  mat - the matrix
3386 .  col - column permutation
3387 -  info - options for factorization, includes
3388 $          fill - expected fill as ratio of original fill.
3389 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3390 $                   Run with the option -info to determine an optimal value to use
3391 
3392    Notes:
3393    Most users should employ the `KSP` interface for linear solvers
3394    instead of working directly with matrix algebra routines such as this.
3395    See, e.g., `KSPCreate()`.
3396 
3397    This changes the state of the matrix to a factored matrix; it cannot be used
3398    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3399 
3400    Level: developer
3401 
3402    Developer Note:
3403    The Fortran interface is not autogenerated as the f90
3404    interface definition cannot be generated correctly [due to MatFactorInfo]
3405 
3406 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3407           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3408 @*/
3409 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3410 {
3411   PetscFunctionBegin;
3412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3413   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3414   if (info) PetscValidPointer(info, 3);
3415   PetscValidType(mat, 1);
3416   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3417   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3418   MatCheckPreallocated(mat, 1);
3419   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3420   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3421   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3422   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3423   PetscFunctionReturn(0);
3424 }
3425 
3426 /*@
3427    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3428    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3429 
3430    Collective on fact
3431 
3432    Input Parameters:
3433 +  fact - the factor matrix obtained with `MatGetFactor()`
3434 .  mat - the matrix
3435 .  col - column permutation
3436 -  info - options for factorization, includes
3437 $          fill - expected fill as ratio of original fill.
3438 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3439 $                   Run with the option -info to determine an optimal value to use
3440 
3441    Most users should employ the `KSP` interface for linear solvers
3442    instead of working directly with matrix algebra routines such as this.
3443    See, e.g., `KSPCreate()`.
3444 
3445    Level: developer
3446 
3447    Developer Note:
3448    The Fortran interface is not autogenerated as the f90
3449    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3450 
3451 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3452 @*/
3453 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3454 {
3455   MatFactorInfo tinfo;
3456 
3457   PetscFunctionBegin;
3458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3459   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3460   if (info) PetscValidPointer(info, 4);
3461   PetscValidType(mat, 2);
3462   PetscValidPointer(fact, 1);
3463   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3464   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3465   MatCheckPreallocated(mat, 2);
3466   if (!info) {
3467     PetscCall(MatFactorInfoInitialize(&tinfo));
3468     info = &tinfo;
3469   }
3470 
3471   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3472   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3473   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3474   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3475   PetscFunctionReturn(0);
3476 }
3477 
3478 /*@
3479    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3480    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3481 
3482    Collective on fact
3483 
3484    Input Parameters:
3485 +  fact - the factor matrix obtained with `MatGetFactor()`
3486 .  mat - the matrix
3487 -  info - options for factorization
3488 
3489    Notes:
3490    See `MatQRFactor()` for in-place factorization.
3491 
3492    Most users should employ the `KSP` interface for linear solvers
3493    instead of working directly with matrix algebra routines such as this.
3494    See, e.g., `KSPCreate()`.
3495 
3496    Level: developer
3497 
3498    Developer Note:
3499    The Fortran interface is not autogenerated as the f90
3500    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3501 
3502 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3503 @*/
3504 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3505 {
3506   MatFactorInfo tinfo;
3507 
3508   PetscFunctionBegin;
3509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3510   PetscValidType(mat, 2);
3511   PetscValidPointer(fact, 1);
3512   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3513   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3514   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,
3515              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3516 
3517   MatCheckPreallocated(mat, 2);
3518   if (!info) {
3519     PetscCall(MatFactorInfoInitialize(&tinfo));
3520     info = &tinfo;
3521   }
3522 
3523   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3524   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3525   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3526   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3527   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3528   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3529   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3530   PetscFunctionReturn(0);
3531 }
3532 
3533 /* ----------------------------------------------------------------*/
3534 /*@
3535    MatSolve - Solves A x = b, given a factored matrix.
3536 
3537    Neighbor-wise Collective on mat
3538 
3539    Input Parameters:
3540 +  mat - the factored matrix
3541 -  b - the right-hand-side vector
3542 
3543    Output Parameter:
3544 .  x - the result vector
3545 
3546    Notes:
3547    The vectors b and x cannot be the same.  I.e., one cannot
3548    call `MatSolve`(A,x,x).
3549 
3550    Most users should employ the `KSP` interface for linear solvers
3551    instead of working directly with matrix algebra routines such as this.
3552    See, e.g., `KSPCreate()`.
3553 
3554    Level: developer
3555 
3556 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3557 @*/
3558 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3559 {
3560   PetscFunctionBegin;
3561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3562   PetscValidType(mat, 1);
3563   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3564   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3565   PetscCheckSameComm(mat, 1, b, 2);
3566   PetscCheckSameComm(mat, 1, x, 3);
3567   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3568   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);
3569   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);
3570   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);
3571   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3572   MatCheckPreallocated(mat, 1);
3573 
3574   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3575   if (mat->factorerrortype) {
3576     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3577     PetscCall(VecSetInf(x));
3578   } else PetscUseTypeMethod(mat, solve, b, x);
3579   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3580   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3581   PetscFunctionReturn(0);
3582 }
3583 
3584 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3585 {
3586   Vec      b, x;
3587   PetscInt N, i;
3588   PetscErrorCode (*f)(Mat, Vec, Vec);
3589   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3590 
3591   PetscFunctionBegin;
3592   if (A->factorerrortype) {
3593     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3594     PetscCall(MatSetInf(X));
3595     PetscFunctionReturn(0);
3596   }
3597   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3598   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3599   PetscCall(MatBoundToCPU(A, &Abound));
3600   if (!Abound) {
3601     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3602     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3603   }
3604 #if defined(PETSC_HAVE_CUDA)
3605   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3606   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3607 #elif (PETSC_HAVE_HIP)
3608   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3609   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3610 #endif
3611   PetscCall(MatGetSize(B, NULL, &N));
3612   for (i = 0; i < N; i++) {
3613     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3614     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3615     PetscCall((*f)(A, b, x));
3616     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3617     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3618   }
3619   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3620   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3621   PetscFunctionReturn(0);
3622 }
3623 
3624 /*@
3625    MatMatSolve - Solves A X = B, given a factored matrix.
3626 
3627    Neighbor-wise Collective on A
3628 
3629    Input Parameters:
3630 +  A - the factored matrix
3631 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3632 
3633    Output Parameter:
3634 .  X - the result matrix (dense matrix)
3635 
3636    Note:
3637    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3638    otherwise, B and X cannot be the same.
3639 
3640    Level: developer
3641 
3642 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3643 @*/
3644 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3645 {
3646   PetscFunctionBegin;
3647   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3648   PetscValidType(A, 1);
3649   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3650   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3651   PetscCheckSameComm(A, 1, B, 2);
3652   PetscCheckSameComm(A, 1, X, 3);
3653   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);
3654   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);
3655   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");
3656   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3657   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3658   MatCheckPreallocated(A, 1);
3659 
3660   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3661   if (!A->ops->matsolve) {
3662     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3663     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3664   } else PetscUseTypeMethod(A, matsolve, B, X);
3665   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3666   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3667   PetscFunctionReturn(0);
3668 }
3669 
3670 /*@
3671    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3672 
3673    Neighbor-wise Collective on A
3674 
3675    Input Parameters:
3676 +  A - the factored matrix
3677 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3678 
3679    Output Parameter:
3680 .  X - the result matrix (dense matrix)
3681 
3682    Note:
3683    The matrices B and X cannot be the same.  I.e., one cannot
3684    call `MatMatSolveTranspose`(A,X,X).
3685 
3686    Level: developer
3687 
3688 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3689 @*/
3690 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3691 {
3692   PetscFunctionBegin;
3693   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3694   PetscValidType(A, 1);
3695   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3696   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3697   PetscCheckSameComm(A, 1, B, 2);
3698   PetscCheckSameComm(A, 1, X, 3);
3699   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3700   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);
3701   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);
3702   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);
3703   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");
3704   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3705   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3706   MatCheckPreallocated(A, 1);
3707 
3708   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3709   if (!A->ops->matsolvetranspose) {
3710     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3711     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3712   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3713   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3714   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3715   PetscFunctionReturn(0);
3716 }
3717 
3718 /*@
3719    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3720 
3721    Neighbor-wise Collective on A
3722 
3723    Input Parameters:
3724 +  A - the factored matrix
3725 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3726 
3727    Output Parameter:
3728 .  X - the result matrix (dense matrix)
3729 
3730    Note:
3731    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
3732    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3733 
3734    Level: developer
3735 
3736 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3737 @*/
3738 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3739 {
3740   PetscFunctionBegin;
3741   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3742   PetscValidType(A, 1);
3743   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3744   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3745   PetscCheckSameComm(A, 1, Bt, 2);
3746   PetscCheckSameComm(A, 1, X, 3);
3747 
3748   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3749   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);
3750   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);
3751   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");
3752   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3753   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3754   MatCheckPreallocated(A, 1);
3755 
3756   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3757   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3758   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3759   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3760   PetscFunctionReturn(0);
3761 }
3762 
3763 /*@
3764    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3765                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3766 
3767    Neighbor-wise Collective on mat
3768 
3769    Input Parameters:
3770 +  mat - the factored matrix
3771 -  b - the right-hand-side vector
3772 
3773    Output Parameter:
3774 .  x - the result vector
3775 
3776    Notes:
3777    `MatSolve()` should be used for most applications, as it performs
3778    a forward solve followed by a backward solve.
3779 
3780    The vectors b and x cannot be the same,  i.e., one cannot
3781    call `MatForwardSolve`(A,x,x).
3782 
3783    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3784    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3785    `MatForwardSolve()` solves U^T*D y = b, and
3786    `MatBackwardSolve()` solves U x = y.
3787    Thus they do not provide a symmetric preconditioner.
3788 
3789    Level: developer
3790 
3791 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3792 @*/
3793 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3794 {
3795   PetscFunctionBegin;
3796   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3797   PetscValidType(mat, 1);
3798   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3799   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3800   PetscCheckSameComm(mat, 1, b, 2);
3801   PetscCheckSameComm(mat, 1, x, 3);
3802   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3803   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);
3804   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);
3805   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);
3806   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3807   MatCheckPreallocated(mat, 1);
3808 
3809   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3810   PetscUseTypeMethod(mat, forwardsolve, b, x);
3811   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3812   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3813   PetscFunctionReturn(0);
3814 }
3815 
3816 /*@
3817    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3818                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3819 
3820    Neighbor-wise Collective on mat
3821 
3822    Input Parameters:
3823 +  mat - the factored matrix
3824 -  b - the right-hand-side vector
3825 
3826    Output Parameter:
3827 .  x - the result vector
3828 
3829    Notes:
3830    `MatSolve()` should be used for most applications, as it performs
3831    a forward solve followed by a backward solve.
3832 
3833    The vectors b and x cannot be the same.  I.e., one cannot
3834    call `MatBackwardSolve`(A,x,x).
3835 
3836    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3837    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3838    `MatForwardSolve()` solves U^T*D y = b, and
3839    `MatBackwardSolve()` solves U x = y.
3840    Thus they do not provide a symmetric preconditioner.
3841 
3842    Level: developer
3843 
3844 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3845 @*/
3846 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3847 {
3848   PetscFunctionBegin;
3849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3850   PetscValidType(mat, 1);
3851   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3852   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3853   PetscCheckSameComm(mat, 1, b, 2);
3854   PetscCheckSameComm(mat, 1, x, 3);
3855   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3856   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);
3857   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);
3858   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);
3859   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3860   MatCheckPreallocated(mat, 1);
3861 
3862   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3863   PetscUseTypeMethod(mat, backwardsolve, b, x);
3864   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3865   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3866   PetscFunctionReturn(0);
3867 }
3868 
3869 /*@
3870    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3871 
3872    Neighbor-wise Collective on mat
3873 
3874    Input Parameters:
3875 +  mat - the factored matrix
3876 .  b - the right-hand-side vector
3877 -  y - the vector to be added to
3878 
3879    Output Parameter:
3880 .  x - the result vector
3881 
3882    Note:
3883    The vectors b and x cannot be the same.  I.e., one cannot
3884    call `MatSolveAdd`(A,x,y,x).
3885 
3886    Level: developer
3887 
3888 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3889 @*/
3890 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3891 {
3892   PetscScalar one = 1.0;
3893   Vec         tmp;
3894 
3895   PetscFunctionBegin;
3896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3897   PetscValidType(mat, 1);
3898   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3899   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3900   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3901   PetscCheckSameComm(mat, 1, b, 2);
3902   PetscCheckSameComm(mat, 1, y, 3);
3903   PetscCheckSameComm(mat, 1, x, 4);
3904   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3905   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);
3906   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);
3907   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);
3908   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);
3909   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);
3910   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3911   MatCheckPreallocated(mat, 1);
3912 
3913   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3914   if (mat->factorerrortype) {
3915     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3916     PetscCall(VecSetInf(x));
3917   } else if (mat->ops->solveadd) {
3918     PetscUseTypeMethod(mat, solveadd, b, y, x);
3919   } else {
3920     /* do the solve then the add manually */
3921     if (x != y) {
3922       PetscCall(MatSolve(mat, b, x));
3923       PetscCall(VecAXPY(x, one, y));
3924     } else {
3925       PetscCall(VecDuplicate(x, &tmp));
3926       PetscCall(VecCopy(x, tmp));
3927       PetscCall(MatSolve(mat, b, x));
3928       PetscCall(VecAXPY(x, one, tmp));
3929       PetscCall(VecDestroy(&tmp));
3930     }
3931   }
3932   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3933   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3934   PetscFunctionReturn(0);
3935 }
3936 
3937 /*@
3938    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3939 
3940    Neighbor-wise Collective on mat
3941 
3942    Input Parameters:
3943 +  mat - the factored matrix
3944 -  b - the right-hand-side vector
3945 
3946    Output Parameter:
3947 .  x - the result vector
3948 
3949    Notes:
3950    The vectors b and x cannot be the same.  I.e., one cannot
3951    call `MatSolveTranspose`(A,x,x).
3952 
3953    Most users should employ the `KSP` interface for linear solvers
3954    instead of working directly with matrix algebra routines such as this.
3955    See, e.g., `KSPCreate()`.
3956 
3957    Level: developer
3958 
3959 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3960 @*/
3961 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3962 {
3963   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3964 
3965   PetscFunctionBegin;
3966   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3967   PetscValidType(mat, 1);
3968   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3969   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3970   PetscCheckSameComm(mat, 1, b, 2);
3971   PetscCheckSameComm(mat, 1, x, 3);
3972   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3973   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);
3974   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);
3975   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3976   MatCheckPreallocated(mat, 1);
3977   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3978   if (mat->factorerrortype) {
3979     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3980     PetscCall(VecSetInf(x));
3981   } else {
3982     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
3983     PetscCall((*f)(mat, b, x));
3984   }
3985   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
3986   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3987   PetscFunctionReturn(0);
3988 }
3989 
3990 /*@
3991    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3992                       factored matrix.
3993 
3994    Neighbor-wise Collective on mat
3995 
3996    Input Parameters:
3997 +  mat - the factored matrix
3998 .  b - the right-hand-side vector
3999 -  y - the vector to be added to
4000 
4001    Output Parameter:
4002 .  x - the result vector
4003 
4004    Note:
4005    The vectors b and x cannot be the same.  I.e., one cannot
4006    call `MatSolveTransposeAdd`(A,x,y,x).
4007 
4008    Level: developer
4009 
4010 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4011 @*/
4012 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4013 {
4014   PetscScalar one = 1.0;
4015   Vec         tmp;
4016   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4017 
4018   PetscFunctionBegin;
4019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4020   PetscValidType(mat, 1);
4021   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4022   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4023   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4024   PetscCheckSameComm(mat, 1, b, 2);
4025   PetscCheckSameComm(mat, 1, y, 3);
4026   PetscCheckSameComm(mat, 1, x, 4);
4027   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4028   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);
4029   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);
4030   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);
4031   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);
4032   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4033   MatCheckPreallocated(mat, 1);
4034 
4035   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4036   if (mat->factorerrortype) {
4037     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4038     PetscCall(VecSetInf(x));
4039   } else if (f) {
4040     PetscCall((*f)(mat, b, y, x));
4041   } else {
4042     /* do the solve then the add manually */
4043     if (x != y) {
4044       PetscCall(MatSolveTranspose(mat, b, x));
4045       PetscCall(VecAXPY(x, one, y));
4046     } else {
4047       PetscCall(VecDuplicate(x, &tmp));
4048       PetscCall(VecCopy(x, tmp));
4049       PetscCall(MatSolveTranspose(mat, b, x));
4050       PetscCall(VecAXPY(x, one, tmp));
4051       PetscCall(VecDestroy(&tmp));
4052     }
4053   }
4054   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4055   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4056   PetscFunctionReturn(0);
4057 }
4058 /* ----------------------------------------------------------------*/
4059 
4060 /*@
4061    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4062 
4063    Neighbor-wise Collective on mat
4064 
4065    Input Parameters:
4066 +  mat - the matrix
4067 .  b - the right hand side
4068 .  omega - the relaxation factor
4069 .  flag - flag indicating the type of SOR (see below)
4070 .  shift -  diagonal shift
4071 .  its - the number of iterations
4072 -  lits - the number of local iterations
4073 
4074    Output Parameter:
4075 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4076 
4077    SOR Flags:
4078 +     `SOR_FORWARD_SWEEP` - forward SOR
4079 .     `SOR_BACKWARD_SWEEP` - backward SOR
4080 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4081 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4082 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4083 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4084 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4085 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4086          upper/lower triangular part of matrix to
4087          vector (with omega)
4088 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4089 
4090    Notes:
4091    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4092    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4093    on each processor.
4094 
4095    Application programmers will not generally use `MatSOR()` directly,
4096    but instead will employ the `KSP`/`PC` interface.
4097 
4098    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4099 
4100    Most users should employ the `KSP` interface for linear solvers
4101    instead of working directly with matrix algebra routines such as this.
4102    See, e.g., `KSPCreate()`.
4103 
4104    Vectors x and b CANNOT be the same
4105 
4106    Notes for Advanced Users:
4107    The flags are implemented as bitwise inclusive or operations.
4108    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4109    to specify a zero initial guess for SSOR.
4110 
4111    Developer Note:
4112    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4113 
4114    Level: developer
4115 
4116 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4117 @*/
4118 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4119 {
4120   PetscFunctionBegin;
4121   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4122   PetscValidType(mat, 1);
4123   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4124   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4125   PetscCheckSameComm(mat, 1, b, 2);
4126   PetscCheckSameComm(mat, 1, x, 8);
4127   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4128   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4129   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);
4130   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);
4131   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);
4132   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4133   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4134   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4135 
4136   MatCheckPreallocated(mat, 1);
4137   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4138   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4139   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4140   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4141   PetscFunctionReturn(0);
4142 }
4143 
4144 /*
4145       Default matrix copy routine.
4146 */
4147 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4148 {
4149   PetscInt           i, rstart = 0, rend = 0, nz;
4150   const PetscInt    *cwork;
4151   const PetscScalar *vwork;
4152 
4153   PetscFunctionBegin;
4154   if (B->assembled) PetscCall(MatZeroEntries(B));
4155   if (str == SAME_NONZERO_PATTERN) {
4156     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4157     for (i = rstart; i < rend; i++) {
4158       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4159       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4160       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4161     }
4162   } else {
4163     PetscCall(MatAYPX(B, 0.0, A, str));
4164   }
4165   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4166   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4167   PetscFunctionReturn(0);
4168 }
4169 
4170 /*@
4171    MatCopy - Copies a matrix to another matrix.
4172 
4173    Collective on A
4174 
4175    Input Parameters:
4176 +  A - the matrix
4177 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4178 
4179    Output Parameter:
4180 .  B - where the copy is put
4181 
4182    Notes:
4183    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4184 
4185    `MatCopy()` copies the matrix entries of a matrix to another existing
4186    matrix (after first zeroing the second matrix).  A related routine is
4187    `MatConvert()`, which first creates a new matrix and then copies the data.
4188 
4189    Level: intermediate
4190 
4191 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4192 @*/
4193 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4194 {
4195   PetscInt i;
4196 
4197   PetscFunctionBegin;
4198   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4199   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4200   PetscValidType(A, 1);
4201   PetscValidType(B, 2);
4202   PetscCheckSameComm(A, 1, B, 2);
4203   MatCheckPreallocated(B, 2);
4204   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4205   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4206   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,
4207              A->cmap->N, B->cmap->N);
4208   MatCheckPreallocated(A, 1);
4209   if (A == B) PetscFunctionReturn(0);
4210 
4211   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4212   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4213   else PetscCall(MatCopy_Basic(A, B, str));
4214 
4215   B->stencil.dim = A->stencil.dim;
4216   B->stencil.noc = A->stencil.noc;
4217   for (i = 0; i <= A->stencil.dim; i++) {
4218     B->stencil.dims[i]   = A->stencil.dims[i];
4219     B->stencil.starts[i] = A->stencil.starts[i];
4220   }
4221 
4222   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4223   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4224   PetscFunctionReturn(0);
4225 }
4226 
4227 /*@C
4228    MatConvert - Converts a matrix to another matrix, either of the same
4229    or different type.
4230 
4231    Collective on mat
4232 
4233    Input Parameters:
4234 +  mat - the matrix
4235 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4236    same type as the original matrix.
4237 -  reuse - denotes if the destination matrix is to be created or reused.
4238    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
4239    `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).
4240 
4241    Output Parameter:
4242 .  M - pointer to place new matrix
4243 
4244    Notes:
4245    `MatConvert()` first creates a new matrix and then copies the data from
4246    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4247    entries of one matrix to another already existing matrix context.
4248 
4249    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4250    the MPI communicator of the generated matrix is always the same as the communicator
4251    of the input matrix.
4252 
4253    Level: intermediate
4254 
4255 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4256 @*/
4257 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4258 {
4259   PetscBool  sametype, issame, flg;
4260   PetscBool3 issymmetric, ishermitian;
4261   char       convname[256], mtype[256];
4262   Mat        B;
4263 
4264   PetscFunctionBegin;
4265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4266   PetscValidType(mat, 1);
4267   PetscValidPointer(M, 4);
4268   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4269   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4270   MatCheckPreallocated(mat, 1);
4271 
4272   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4273   if (flg) newtype = mtype;
4274 
4275   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4276   PetscCall(PetscStrcmp(newtype, "same", &issame));
4277   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4278   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");
4279 
4280   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4281     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4282     PetscFunctionReturn(0);
4283   }
4284 
4285   /* Cache Mat options because some converters use MatHeaderReplace  */
4286   issymmetric = mat->symmetric;
4287   ishermitian = mat->hermitian;
4288 
4289   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4290     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4291     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4292   } else {
4293     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4294     const char *prefix[3]                                 = {"seq", "mpi", ""};
4295     PetscInt    i;
4296     /*
4297        Order of precedence:
4298        0) See if newtype is a superclass of the current matrix.
4299        1) See if a specialized converter is known to the current matrix.
4300        2) See if a specialized converter is known to the desired matrix class.
4301        3) See if a good general converter is registered for the desired class
4302           (as of 6/27/03 only MATMPIADJ falls into this category).
4303        4) See if a good general converter is known for the current matrix.
4304        5) Use a really basic converter.
4305     */
4306 
4307     /* 0) See if newtype is a superclass of the current matrix.
4308           i.e mat is mpiaij and newtype is aij */
4309     for (i = 0; i < 2; i++) {
4310       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4311       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4312       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4313       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4314       if (flg) {
4315         if (reuse == MAT_INPLACE_MATRIX) {
4316           PetscCall(PetscInfo(mat, "Early return\n"));
4317           PetscFunctionReturn(0);
4318         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4319           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4320           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4321           PetscFunctionReturn(0);
4322         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4323           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4324           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4325           PetscFunctionReturn(0);
4326         }
4327       }
4328     }
4329     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4330     for (i = 0; i < 3; i++) {
4331       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4332       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4333       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4334       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4335       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4336       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4337       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4338       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4339       if (conv) goto foundconv;
4340     }
4341 
4342     /* 2)  See if a specialized converter is known to the desired matrix class. */
4343     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4344     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4345     PetscCall(MatSetType(B, newtype));
4346     for (i = 0; i < 3; i++) {
4347       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4348       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4351       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4353       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4354       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4355       if (conv) {
4356         PetscCall(MatDestroy(&B));
4357         goto foundconv;
4358       }
4359     }
4360 
4361     /* 3) See if a good general converter is registered for the desired class */
4362     conv = B->ops->convertfrom;
4363     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4364     PetscCall(MatDestroy(&B));
4365     if (conv) goto foundconv;
4366 
4367     /* 4) See if a good general converter is known for the current matrix */
4368     if (mat->ops->convert) conv = mat->ops->convert;
4369     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4370     if (conv) goto foundconv;
4371 
4372     /* 5) Use a really basic converter. */
4373     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4374     conv = MatConvert_Basic;
4375 
4376   foundconv:
4377     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4378     PetscCall((*conv)(mat, newtype, reuse, M));
4379     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4380       /* the block sizes must be same if the mappings are copied over */
4381       (*M)->rmap->bs = mat->rmap->bs;
4382       (*M)->cmap->bs = mat->cmap->bs;
4383       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4384       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4385       (*M)->rmap->mapping = mat->rmap->mapping;
4386       (*M)->cmap->mapping = mat->cmap->mapping;
4387     }
4388     (*M)->stencil.dim = mat->stencil.dim;
4389     (*M)->stencil.noc = mat->stencil.noc;
4390     for (i = 0; i <= mat->stencil.dim; i++) {
4391       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4392       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4393     }
4394     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4395   }
4396   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4397 
4398   /* Copy Mat options */
4399   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4400   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4401   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4402   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4403   PetscFunctionReturn(0);
4404 }
4405 
4406 /*@C
4407    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4408 
4409    Not Collective
4410 
4411    Input Parameter:
4412 .  mat - the matrix, must be a factored matrix
4413 
4414    Output Parameter:
4415 .   type - the string name of the package (do not free this string)
4416 
4417    Note:
4418       In Fortran you pass in a empty string and the package name will be copied into it.
4419     (Make sure the string is long enough)
4420 
4421    Level: intermediate
4422 
4423 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4424 @*/
4425 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4426 {
4427   PetscErrorCode (*conv)(Mat, MatSolverType *);
4428 
4429   PetscFunctionBegin;
4430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4431   PetscValidType(mat, 1);
4432   PetscValidPointer(type, 2);
4433   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4434   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4435   if (conv) PetscCall((*conv)(mat, type));
4436   else *type = MATSOLVERPETSC;
4437   PetscFunctionReturn(0);
4438 }
4439 
4440 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4441 struct _MatSolverTypeForSpecifcType {
4442   MatType mtype;
4443   /* no entry for MAT_FACTOR_NONE */
4444   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4445   MatSolverTypeForSpecifcType next;
4446 };
4447 
4448 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4449 struct _MatSolverTypeHolder {
4450   char                       *name;
4451   MatSolverTypeForSpecifcType handlers;
4452   MatSolverTypeHolder         next;
4453 };
4454 
4455 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4456 
4457 /*@C
4458    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4459 
4460    Input Parameters:
4461 +    package - name of the package, for example petsc or superlu
4462 .    mtype - the matrix type that works with this package
4463 .    ftype - the type of factorization supported by the package
4464 -    createfactor - routine that will create the factored matrix ready to be used
4465 
4466     Level: developer
4467 
4468 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4469 @*/
4470 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4471 {
4472   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4473   PetscBool                   flg;
4474   MatSolverTypeForSpecifcType inext, iprev = NULL;
4475 
4476   PetscFunctionBegin;
4477   PetscCall(MatInitializePackage());
4478   if (!next) {
4479     PetscCall(PetscNew(&MatSolverTypeHolders));
4480     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4481     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4482     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4483     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4484     PetscFunctionReturn(0);
4485   }
4486   while (next) {
4487     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4488     if (flg) {
4489       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4490       inext = next->handlers;
4491       while (inext) {
4492         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4493         if (flg) {
4494           inext->createfactor[(int)ftype - 1] = createfactor;
4495           PetscFunctionReturn(0);
4496         }
4497         iprev = inext;
4498         inext = inext->next;
4499       }
4500       PetscCall(PetscNew(&iprev->next));
4501       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4502       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4503       PetscFunctionReturn(0);
4504     }
4505     prev = next;
4506     next = next->next;
4507   }
4508   PetscCall(PetscNew(&prev->next));
4509   PetscCall(PetscStrallocpy(package, &prev->next->name));
4510   PetscCall(PetscNew(&prev->next->handlers));
4511   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4512   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4513   PetscFunctionReturn(0);
4514 }
4515 
4516 /*@C
4517    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4518 
4519    Input Parameters:
4520 +    type - name of the package, for example petsc or superlu
4521 .    ftype - the type of factorization supported by the type
4522 -    mtype - the matrix type that works with this type
4523 
4524    Output Parameters:
4525 +   foundtype - `PETSC_TRUE` if the type was registered
4526 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4527 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4528 
4529     Level: developer
4530 
4531 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4532 @*/
4533 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4534 {
4535   MatSolverTypeHolder         next = MatSolverTypeHolders;
4536   PetscBool                   flg;
4537   MatSolverTypeForSpecifcType inext;
4538 
4539   PetscFunctionBegin;
4540   if (foundtype) *foundtype = PETSC_FALSE;
4541   if (foundmtype) *foundmtype = PETSC_FALSE;
4542   if (createfactor) *createfactor = NULL;
4543 
4544   if (type) {
4545     while (next) {
4546       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4547       if (flg) {
4548         if (foundtype) *foundtype = PETSC_TRUE;
4549         inext = next->handlers;
4550         while (inext) {
4551           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4552           if (flg) {
4553             if (foundmtype) *foundmtype = PETSC_TRUE;
4554             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4555             PetscFunctionReturn(0);
4556           }
4557           inext = inext->next;
4558         }
4559       }
4560       next = next->next;
4561     }
4562   } else {
4563     while (next) {
4564       inext = next->handlers;
4565       while (inext) {
4566         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4567         if (flg && inext->createfactor[(int)ftype - 1]) {
4568           if (foundtype) *foundtype = PETSC_TRUE;
4569           if (foundmtype) *foundmtype = PETSC_TRUE;
4570           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4571           PetscFunctionReturn(0);
4572         }
4573         inext = inext->next;
4574       }
4575       next = next->next;
4576     }
4577     /* try with base classes inext->mtype */
4578     next = MatSolverTypeHolders;
4579     while (next) {
4580       inext = next->handlers;
4581       while (inext) {
4582         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4583         if (flg && inext->createfactor[(int)ftype - 1]) {
4584           if (foundtype) *foundtype = PETSC_TRUE;
4585           if (foundmtype) *foundmtype = PETSC_TRUE;
4586           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4587           PetscFunctionReturn(0);
4588         }
4589         inext = inext->next;
4590       }
4591       next = next->next;
4592     }
4593   }
4594   PetscFunctionReturn(0);
4595 }
4596 
4597 PetscErrorCode MatSolverTypeDestroy(void)
4598 {
4599   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4600   MatSolverTypeForSpecifcType inext, iprev;
4601 
4602   PetscFunctionBegin;
4603   while (next) {
4604     PetscCall(PetscFree(next->name));
4605     inext = next->handlers;
4606     while (inext) {
4607       PetscCall(PetscFree(inext->mtype));
4608       iprev = inext;
4609       inext = inext->next;
4610       PetscCall(PetscFree(iprev));
4611     }
4612     prev = next;
4613     next = next->next;
4614     PetscCall(PetscFree(prev));
4615   }
4616   MatSolverTypeHolders = NULL;
4617   PetscFunctionReturn(0);
4618 }
4619 
4620 /*@C
4621    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4622 
4623    Logically Collective on mat
4624 
4625    Input Parameters:
4626 .  mat - the matrix
4627 
4628    Output Parameters:
4629 .  flg - `PETSC_TRUE` if uses the ordering
4630 
4631    Note:
4632    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4633    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4634 
4635    Level: developer
4636 
4637 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4638 @*/
4639 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4640 {
4641   PetscFunctionBegin;
4642   *flg = mat->canuseordering;
4643   PetscFunctionReturn(0);
4644 }
4645 
4646 /*@C
4647    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4648 
4649    Logically Collective on mat
4650 
4651    Input Parameters:
4652 .  mat - the matrix obtained with `MatGetFactor()`
4653 
4654    Output Parameters:
4655 .  otype - the preferred type
4656 
4657    Level: developer
4658 
4659 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4660 @*/
4661 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4662 {
4663   PetscFunctionBegin;
4664   *otype = mat->preferredordering[ftype];
4665   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4666   PetscFunctionReturn(0);
4667 }
4668 
4669 /*@C
4670    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4671 
4672    Collective on mat
4673 
4674    Input Parameters:
4675 +  mat - the matrix
4676 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4677 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4678 
4679    Output Parameters:
4680 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4681 
4682    Options Database Key:
4683 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4684                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4685 
4686    Notes:
4687      Users usually access the factorization solvers via `KSP`
4688 
4689       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4690      such as pastix, superlu, mumps etc.
4691 
4692       PETSc must have been ./configure to use the external solver, using the option --download-package
4693 
4694       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4695       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4696       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4697 
4698    Developer Note:
4699       This should actually be called `MatCreateFactor()` since it creates a new factor object
4700 
4701    Level: intermediate
4702 
4703 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4704           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4705 @*/
4706 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4707 {
4708   PetscBool foundtype, foundmtype;
4709   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4710 
4711   PetscFunctionBegin;
4712   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4713   PetscValidType(mat, 1);
4714 
4715   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4716   MatCheckPreallocated(mat, 1);
4717 
4718   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4719   if (!foundtype) {
4720     if (type) {
4721       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],
4722               ((PetscObject)mat)->type_name, type);
4723     } else {
4724       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);
4725     }
4726   }
4727   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4728   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);
4729 
4730   PetscCall((*conv)(mat, ftype, f));
4731   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4732   PetscFunctionReturn(0);
4733 }
4734 
4735 /*@C
4736    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4737 
4738    Not Collective
4739 
4740    Input Parameters:
4741 +  mat - the matrix
4742 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4743 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4744 
4745    Output Parameter:
4746 .    flg - PETSC_TRUE if the factorization is available
4747 
4748    Notes:
4749       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4750      such as pastix, superlu, mumps etc.
4751 
4752       PETSc must have been ./configure to use the external solver, using the option --download-package
4753 
4754    Developer Note:
4755       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4756 
4757    Level: intermediate
4758 
4759 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4760           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4761 @*/
4762 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4763 {
4764   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4765 
4766   PetscFunctionBegin;
4767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4768   PetscValidType(mat, 1);
4769   PetscValidBoolPointer(flg, 4);
4770 
4771   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4772   MatCheckPreallocated(mat, 1);
4773 
4774   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4775   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4776   PetscFunctionReturn(0);
4777 }
4778 
4779 /*@
4780    MatDuplicate - Duplicates a matrix including the non-zero structure.
4781 
4782    Collective on mat
4783 
4784    Input Parameters:
4785 +  mat - the matrix
4786 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4787         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4788 
4789    Output Parameter:
4790 .  M - pointer to place new matrix
4791 
4792    Level: intermediate
4793 
4794    Notes:
4795     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4796 
4797     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.
4798 
4799     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
4800     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4801     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4802 
4803 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4804 @*/
4805 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4806 {
4807   Mat         B;
4808   VecType     vtype;
4809   PetscInt    i;
4810   PetscObject dm;
4811   void (*viewf)(void);
4812 
4813   PetscFunctionBegin;
4814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4815   PetscValidType(mat, 1);
4816   PetscValidPointer(M, 3);
4817   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4818   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4819   MatCheckPreallocated(mat, 1);
4820 
4821   *M = NULL;
4822   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4823   PetscUseTypeMethod(mat, duplicate, op, M);
4824   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4825   B = *M;
4826 
4827   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4828   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4829   PetscCall(MatGetVecType(mat, &vtype));
4830   PetscCall(MatSetVecType(B, vtype));
4831 
4832   B->stencil.dim = mat->stencil.dim;
4833   B->stencil.noc = mat->stencil.noc;
4834   for (i = 0; i <= mat->stencil.dim; i++) {
4835     B->stencil.dims[i]   = mat->stencil.dims[i];
4836     B->stencil.starts[i] = mat->stencil.starts[i];
4837   }
4838 
4839   B->nooffproczerorows = mat->nooffproczerorows;
4840   B->nooffprocentries  = mat->nooffprocentries;
4841 
4842   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4843   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4844   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4845   PetscFunctionReturn(0);
4846 }
4847 
4848 /*@
4849    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4850 
4851    Logically Collective on mat
4852 
4853    Input Parameters:
4854 +  mat - the matrix
4855 -  v - the vector for storing the diagonal
4856 
4857    Output Parameter:
4858 .  v - the diagonal of the matrix
4859 
4860    Level: intermediate
4861 
4862    Note:
4863    Currently only correct in parallel for square matrices.
4864 
4865 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4866 @*/
4867 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4868 {
4869   PetscFunctionBegin;
4870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4871   PetscValidType(mat, 1);
4872   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4873   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4874   MatCheckPreallocated(mat, 1);
4875 
4876   PetscUseTypeMethod(mat, getdiagonal, v);
4877   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4878   PetscFunctionReturn(0);
4879 }
4880 
4881 /*@C
4882    MatGetRowMin - Gets the minimum value (of the real part) of each
4883         row of the matrix
4884 
4885    Logically Collective on mat
4886 
4887    Input Parameter:
4888 .  mat - the matrix
4889 
4890    Output Parameters:
4891 +  v - the vector for storing the maximums
4892 -  idx - the indices of the column found for each row (optional)
4893 
4894    Level: intermediate
4895 
4896    Note:
4897     The result of this call are the same as if one converted the matrix to dense format
4898       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4899 
4900     This code is only implemented for a couple of matrix formats.
4901 
4902 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4903           `MatGetRowMax()`
4904 @*/
4905 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4906 {
4907   PetscFunctionBegin;
4908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4909   PetscValidType(mat, 1);
4910   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4911   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4912 
4913   if (!mat->cmap->N) {
4914     PetscCall(VecSet(v, PETSC_MAX_REAL));
4915     if (idx) {
4916       PetscInt i, m = mat->rmap->n;
4917       for (i = 0; i < m; i++) idx[i] = -1;
4918     }
4919   } else {
4920     MatCheckPreallocated(mat, 1);
4921   }
4922   PetscUseTypeMethod(mat, getrowmin, v, idx);
4923   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4924   PetscFunctionReturn(0);
4925 }
4926 
4927 /*@C
4928    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4929         row of the matrix
4930 
4931    Logically Collective on mat
4932 
4933    Input Parameter:
4934 .  mat - the matrix
4935 
4936    Output Parameters:
4937 +  v - the vector for storing the minimums
4938 -  idx - the indices of the column found for each row (or NULL if not needed)
4939 
4940    Level: intermediate
4941 
4942    Notes:
4943     if a row is completely empty or has only 0.0 values then the idx[] value for that
4944     row is 0 (the first column).
4945 
4946     This code is only implemented for a couple of matrix formats.
4947 
4948 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4949 @*/
4950 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4951 {
4952   PetscFunctionBegin;
4953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4954   PetscValidType(mat, 1);
4955   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4956   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4957   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4958 
4959   if (!mat->cmap->N) {
4960     PetscCall(VecSet(v, 0.0));
4961     if (idx) {
4962       PetscInt i, m = mat->rmap->n;
4963       for (i = 0; i < m; i++) idx[i] = -1;
4964     }
4965   } else {
4966     MatCheckPreallocated(mat, 1);
4967     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4968     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4969   }
4970   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4971   PetscFunctionReturn(0);
4972 }
4973 
4974 /*@C
4975    MatGetRowMax - Gets the maximum value (of the real part) of each
4976         row of the matrix
4977 
4978    Logically Collective on mat
4979 
4980    Input Parameter:
4981 .  mat - the matrix
4982 
4983    Output Parameters:
4984 +  v - the vector for storing the maximums
4985 -  idx - the indices of the column found for each row (optional)
4986 
4987    Level: intermediate
4988 
4989    Notes:
4990     The result of this call are the same as if one converted the matrix to dense format
4991       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4992 
4993     This code is only implemented for a couple of matrix formats.
4994 
4995 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4996 @*/
4997 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4998 {
4999   PetscFunctionBegin;
5000   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5001   PetscValidType(mat, 1);
5002   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5003   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5004 
5005   if (!mat->cmap->N) {
5006     PetscCall(VecSet(v, PETSC_MIN_REAL));
5007     if (idx) {
5008       PetscInt i, m = mat->rmap->n;
5009       for (i = 0; i < m; i++) idx[i] = -1;
5010     }
5011   } else {
5012     MatCheckPreallocated(mat, 1);
5013     PetscUseTypeMethod(mat, getrowmax, v, idx);
5014   }
5015   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5016   PetscFunctionReturn(0);
5017 }
5018 
5019 /*@C
5020    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5021         row of the matrix
5022 
5023    Logically Collective on mat
5024 
5025    Input Parameter:
5026 .  mat - the matrix
5027 
5028    Output Parameters:
5029 +  v - the vector for storing the maximums
5030 -  idx - the indices of the column found for each row (or NULL if not needed)
5031 
5032    Level: intermediate
5033 
5034    Notes:
5035     if a row is completely empty or has only 0.0 values then the idx[] value for that
5036     row is 0 (the first column).
5037 
5038     This code is only implemented for a couple of matrix formats.
5039 
5040 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5041 @*/
5042 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5043 {
5044   PetscFunctionBegin;
5045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5046   PetscValidType(mat, 1);
5047   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5048   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5049 
5050   if (!mat->cmap->N) {
5051     PetscCall(VecSet(v, 0.0));
5052     if (idx) {
5053       PetscInt i, m = mat->rmap->n;
5054       for (i = 0; i < m; i++) idx[i] = -1;
5055     }
5056   } else {
5057     MatCheckPreallocated(mat, 1);
5058     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5059     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5060   }
5061   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5062   PetscFunctionReturn(0);
5063 }
5064 
5065 /*@
5066    MatGetRowSum - Gets the sum of each row of the matrix
5067 
5068    Logically or Neighborhood Collective on mat
5069 
5070    Input Parameters:
5071 .  mat - the matrix
5072 
5073    Output Parameter:
5074 .  v - the vector for storing the sum of rows
5075 
5076    Level: intermediate
5077 
5078    Notes:
5079     This code is slow since it is not currently specialized for different formats
5080 
5081 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5082 @*/
5083 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5084 {
5085   Vec ones;
5086 
5087   PetscFunctionBegin;
5088   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5089   PetscValidType(mat, 1);
5090   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5091   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5092   MatCheckPreallocated(mat, 1);
5093   PetscCall(MatCreateVecs(mat, &ones, NULL));
5094   PetscCall(VecSet(ones, 1.));
5095   PetscCall(MatMult(mat, ones, v));
5096   PetscCall(VecDestroy(&ones));
5097   PetscFunctionReturn(0);
5098 }
5099 
5100 /*@
5101    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5102    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5103 
5104    Collective on mat
5105 
5106    Input Parameter:
5107 .  mat - the matrix to provide the transpose
5108 
5109    Output Parameter:
5110 .  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
5111 
5112    Level: advanced
5113 
5114    Note:
5115    Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This
5116    routine allows bypassing that call.
5117 
5118 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5119 @*/
5120 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5121 {
5122   PetscContainer  rB = NULL;
5123   MatParentState *rb = NULL;
5124 
5125   PetscFunctionBegin;
5126   PetscCall(PetscNew(&rb));
5127   rb->id    = ((PetscObject)mat)->id;
5128   rb->state = 0;
5129   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5130   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5131   PetscCall(PetscContainerSetPointer(rB, rb));
5132   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5133   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5134   PetscCall(PetscObjectDereference((PetscObject)rB));
5135   PetscFunctionReturn(0);
5136 }
5137 
5138 /*@
5139    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5140 
5141    Collective on mat
5142 
5143    Input Parameters:
5144 +  mat - the matrix to transpose
5145 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5146 
5147    Output Parameter:
5148 .  B - the transpose
5149 
5150    Notes:
5151      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5152 
5153      `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
5154      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5155 
5156      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.
5157 
5158      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5159 
5160      If mat is unchanged from the last call this function returns immediately without recomputing the result
5161 
5162      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5163 
5164    Level: intermediate
5165 
5166 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5167           `MatTransposeSymbolic()`
5168 @*/
5169 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5170 {
5171   PetscContainer  rB = NULL;
5172   MatParentState *rb = NULL;
5173 
5174   PetscFunctionBegin;
5175   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5176   PetscValidType(mat, 1);
5177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5179   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5180   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5181   MatCheckPreallocated(mat, 1);
5182   if (reuse == MAT_REUSE_MATRIX) {
5183     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5184     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5185     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5186     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5187     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5188   }
5189 
5190   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5191   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5192     PetscUseTypeMethod(mat, transpose, reuse, B);
5193     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5194   }
5195   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5196 
5197   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5198   if (reuse != MAT_INPLACE_MATRIX) {
5199     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5200     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5201     rb->state        = ((PetscObject)mat)->state;
5202     rb->nonzerostate = mat->nonzerostate;
5203   }
5204   PetscFunctionReturn(0);
5205 }
5206 
5207 /*@
5208    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5209 
5210    Collective on A
5211 
5212    Input Parameters:
5213 .  A - the matrix to transpose
5214 
5215    Output Parameter:
5216 .  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
5217       numerical portion.
5218 
5219    Level: intermediate
5220 
5221    Note:
5222    This is not supported for many matrix types, use `MatTranspose()` in those cases
5223 
5224 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5225 @*/
5226 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5227 {
5228   PetscFunctionBegin;
5229   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5230   PetscValidType(A, 1);
5231   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5232   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5233   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5234   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5235   PetscCall((*A->ops->transposesymbolic)(A, B));
5236   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5237 
5238   PetscCall(MatTransposeSetPrecursor(A, *B));
5239   PetscFunctionReturn(0);
5240 }
5241 
5242 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5243 {
5244   PetscContainer  rB;
5245   MatParentState *rb;
5246 
5247   PetscFunctionBegin;
5248   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5249   PetscValidType(A, 1);
5250   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5251   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5252   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5253   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5254   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5255   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5256   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5257   PetscFunctionReturn(0);
5258 }
5259 
5260 /*@
5261    MatIsTranspose - Test whether a matrix is another one's transpose,
5262         or its own, in which case it tests symmetry.
5263 
5264    Collective on A
5265 
5266    Input Parameters:
5267 +  A - the matrix to test
5268 -  B - the matrix to test against, this can equal the first parameter
5269 
5270    Output Parameters:
5271 .  flg - the result
5272 
5273    Notes:
5274    Only available for `MATAIJ` matrices.
5275 
5276    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5277    test involves parallel copies of the block-offdiagonal parts of the matrix.
5278 
5279    Level: intermediate
5280 
5281 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5282 @*/
5283 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5284 {
5285   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5286 
5287   PetscFunctionBegin;
5288   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5289   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5290   PetscValidBoolPointer(flg, 4);
5291   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5292   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5293   *flg = PETSC_FALSE;
5294   if (f && g) {
5295     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5296     PetscCall((*f)(A, B, tol, flg));
5297   } else {
5298     MatType mattype;
5299 
5300     PetscCall(MatGetType(f ? B : A, &mattype));
5301     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5302   }
5303   PetscFunctionReturn(0);
5304 }
5305 
5306 /*@
5307    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5308 
5309    Collective on mat
5310 
5311    Input Parameters:
5312 +  mat - the matrix to transpose and complex conjugate
5313 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5314 
5315    Output Parameter:
5316 .  B - the Hermitian transpose
5317 
5318    Level: intermediate
5319 
5320 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5321 @*/
5322 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5323 {
5324   PetscFunctionBegin;
5325   PetscCall(MatTranspose(mat, reuse, B));
5326 #if defined(PETSC_USE_COMPLEX)
5327   PetscCall(MatConjugate(*B));
5328 #endif
5329   PetscFunctionReturn(0);
5330 }
5331 
5332 /*@
5333    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5334 
5335    Collective on A
5336 
5337    Input Parameters:
5338 +  A - the matrix to test
5339 -  B - the matrix to test against, this can equal the first parameter
5340 
5341    Output Parameters:
5342 .  flg - the result
5343 
5344    Notes:
5345    Only available for `MATAIJ` matrices.
5346 
5347    The sequential algorithm
5348    has a running time of the order of the number of nonzeros; the parallel
5349    test involves parallel copies of the block-offdiagonal parts of the matrix.
5350 
5351    Level: intermediate
5352 
5353 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5354 @*/
5355 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5356 {
5357   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5358 
5359   PetscFunctionBegin;
5360   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5361   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5362   PetscValidBoolPointer(flg, 4);
5363   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5364   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5365   if (f && g) {
5366     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5367     PetscCall((*f)(A, B, tol, flg));
5368   }
5369   PetscFunctionReturn(0);
5370 }
5371 
5372 /*@
5373    MatPermute - Creates a new matrix with rows and columns permuted from the
5374    original.
5375 
5376    Collective on mat
5377 
5378    Input Parameters:
5379 +  mat - the matrix to permute
5380 .  row - row permutation, each processor supplies only the permutation for its rows
5381 -  col - column permutation, each processor supplies only the permutation for its columns
5382 
5383    Output Parameters:
5384 .  B - the permuted matrix
5385 
5386    Level: advanced
5387 
5388    Note:
5389    The index sets map from row/col of permuted matrix to row/col of original matrix.
5390    The index sets should be on the same communicator as mat and have the same local sizes.
5391 
5392    Developer Note:
5393      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5394      exploit the fact that row and col are permutations, consider implementing the
5395      more general `MatCreateSubMatrix()` instead.
5396 
5397 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5398 @*/
5399 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5400 {
5401   PetscFunctionBegin;
5402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5403   PetscValidType(mat, 1);
5404   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5405   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5406   PetscValidPointer(B, 4);
5407   PetscCheckSameComm(mat, 1, row, 2);
5408   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5409   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5410   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5411   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5412   MatCheckPreallocated(mat, 1);
5413 
5414   if (mat->ops->permute) {
5415     PetscUseTypeMethod(mat, permute, row, col, B);
5416     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5417   } else {
5418     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5419   }
5420   PetscFunctionReturn(0);
5421 }
5422 
5423 /*@
5424    MatEqual - Compares two matrices.
5425 
5426    Collective on A
5427 
5428    Input Parameters:
5429 +  A - the first matrix
5430 -  B - the second matrix
5431 
5432    Output Parameter:
5433 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5434 
5435    Level: intermediate
5436 
5437 .seealso: `Mat`
5438 @*/
5439 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5440 {
5441   PetscFunctionBegin;
5442   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5443   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5444   PetscValidType(A, 1);
5445   PetscValidType(B, 2);
5446   PetscValidBoolPointer(flg, 3);
5447   PetscCheckSameComm(A, 1, B, 2);
5448   MatCheckPreallocated(A, 1);
5449   MatCheckPreallocated(B, 2);
5450   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5451   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5452   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,
5453              B->cmap->N);
5454   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5455     PetscUseTypeMethod(A, equal, B, flg);
5456   } else {
5457     PetscCall(MatMultEqual(A, B, 10, flg));
5458   }
5459   PetscFunctionReturn(0);
5460 }
5461 
5462 /*@
5463    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5464    matrices that are stored as vectors.  Either of the two scaling
5465    matrices can be NULL.
5466 
5467    Collective on mat
5468 
5469    Input Parameters:
5470 +  mat - the matrix to be scaled
5471 .  l - the left scaling vector (or NULL)
5472 -  r - the right scaling vector (or NULL)
5473 
5474    Note:
5475    `MatDiagonalScale()` computes A = LAR, where
5476    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5477    The L scales the rows of the matrix, the R scales the columns of the matrix.
5478 
5479    Level: intermediate
5480 
5481 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5482 @*/
5483 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5484 {
5485   PetscFunctionBegin;
5486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5487   PetscValidType(mat, 1);
5488   if (l) {
5489     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5490     PetscCheckSameComm(mat, 1, l, 2);
5491   }
5492   if (r) {
5493     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5494     PetscCheckSameComm(mat, 1, r, 3);
5495   }
5496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5498   MatCheckPreallocated(mat, 1);
5499   if (!l && !r) PetscFunctionReturn(0);
5500 
5501   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5502   PetscUseTypeMethod(mat, diagonalscale, l, r);
5503   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5504   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5505   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5506   PetscFunctionReturn(0);
5507 }
5508 
5509 /*@
5510     MatScale - Scales all elements of a matrix by a given number.
5511 
5512     Logically Collective on mat
5513 
5514     Input Parameters:
5515 +   mat - the matrix to be scaled
5516 -   a  - the scaling value
5517 
5518     Output Parameter:
5519 .   mat - the scaled matrix
5520 
5521     Level: intermediate
5522 
5523 .seealso: `Mat`, `MatDiagonalScale()`
5524 @*/
5525 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5526 {
5527   PetscFunctionBegin;
5528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5529   PetscValidType(mat, 1);
5530   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5531   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5532   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5533   PetscValidLogicalCollectiveScalar(mat, a, 2);
5534   MatCheckPreallocated(mat, 1);
5535 
5536   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5537   if (a != (PetscScalar)1.0) {
5538     PetscUseTypeMethod(mat, scale, a);
5539     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5540   }
5541   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5542   PetscFunctionReturn(0);
5543 }
5544 
5545 /*@
5546    MatNorm - Calculates various norms of a matrix.
5547 
5548    Collective on mat
5549 
5550    Input Parameters:
5551 +  mat - the matrix
5552 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5553 
5554    Output Parameter:
5555 .  nrm - the resulting norm
5556 
5557    Level: intermediate
5558 
5559 .seealso: `Mat`
5560 @*/
5561 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5562 {
5563   PetscFunctionBegin;
5564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5565   PetscValidType(mat, 1);
5566   PetscValidRealPointer(nrm, 3);
5567 
5568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5570   MatCheckPreallocated(mat, 1);
5571 
5572   PetscUseTypeMethod(mat, norm, type, nrm);
5573   PetscFunctionReturn(0);
5574 }
5575 
5576 /*
5577      This variable is used to prevent counting of MatAssemblyBegin() that
5578    are called from within a MatAssemblyEnd().
5579 */
5580 static PetscInt MatAssemblyEnd_InUse = 0;
5581 /*@
5582    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5583    be called after completing all calls to `MatSetValues()`.
5584 
5585    Collective on mat
5586 
5587    Input Parameters:
5588 +  mat - the matrix
5589 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5590 
5591    Notes:
5592    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5593    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5594 
5595    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5596    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5597    using the matrix.
5598 
5599    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5600    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
5601    a global collective operation requiring all processes that share the matrix.
5602 
5603    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5604    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5605    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5606 
5607    Level: beginner
5608 
5609 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5610 @*/
5611 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5612 {
5613   PetscFunctionBegin;
5614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5615   PetscValidType(mat, 1);
5616   MatCheckPreallocated(mat, 1);
5617   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5618   if (mat->assembled) {
5619     mat->was_assembled = PETSC_TRUE;
5620     mat->assembled     = PETSC_FALSE;
5621   }
5622 
5623   if (!MatAssemblyEnd_InUse) {
5624     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5625     PetscTryTypeMethod(mat, assemblybegin, type);
5626     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5627   } else PetscTryTypeMethod(mat, assemblybegin, type);
5628   PetscFunctionReturn(0);
5629 }
5630 
5631 /*@
5632    MatAssembled - Indicates if a matrix has been assembled and is ready for
5633      use; for example, in matrix-vector product.
5634 
5635    Not Collective
5636 
5637    Input Parameter:
5638 .  mat - the matrix
5639 
5640    Output Parameter:
5641 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5642 
5643    Level: advanced
5644 
5645 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5646 @*/
5647 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5648 {
5649   PetscFunctionBegin;
5650   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5651   PetscValidBoolPointer(assembled, 2);
5652   *assembled = mat->assembled;
5653   PetscFunctionReturn(0);
5654 }
5655 
5656 /*@
5657    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5658    be called after `MatAssemblyBegin()`.
5659 
5660    Collective on Mat
5661 
5662    Input Parameters:
5663 +  mat - the matrix
5664 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5665 
5666    Options Database Keys:
5667 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5668 .  -mat_view ::ascii_info_detail - Prints more detailed info
5669 .  -mat_view - Prints matrix in ASCII format
5670 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5671 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5672 .  -display <name> - Sets display name (default is host)
5673 .  -draw_pause <sec> - Sets number of seconds to pause after display
5674 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5675 .  -viewer_socket_machine <machine> - Machine to use for socket
5676 .  -viewer_socket_port <port> - Port number to use for socket
5677 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5678 
5679    Level: beginner
5680 
5681 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5682 @*/
5683 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5684 {
5685   static PetscInt inassm = 0;
5686   PetscBool       flg    = PETSC_FALSE;
5687 
5688   PetscFunctionBegin;
5689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5690   PetscValidType(mat, 1);
5691 
5692   inassm++;
5693   MatAssemblyEnd_InUse++;
5694   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5695     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5696     PetscTryTypeMethod(mat, assemblyend, type);
5697     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5698   } else PetscTryTypeMethod(mat, assemblyend, type);
5699 
5700   /* Flush assembly is not a true assembly */
5701   if (type != MAT_FLUSH_ASSEMBLY) {
5702     if (mat->num_ass) {
5703       if (!mat->symmetry_eternal) {
5704         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5705         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5706       }
5707       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5708       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5709     }
5710     mat->num_ass++;
5711     mat->assembled        = PETSC_TRUE;
5712     mat->ass_nonzerostate = mat->nonzerostate;
5713   }
5714 
5715   mat->insertmode = NOT_SET_VALUES;
5716   MatAssemblyEnd_InUse--;
5717   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5718   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5719     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5720 
5721     if (mat->checksymmetryonassembly) {
5722       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5723       if (flg) {
5724         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5725       } else {
5726         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5727       }
5728     }
5729     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5730   }
5731   inassm--;
5732   PetscFunctionReturn(0);
5733 }
5734 
5735 /*@
5736    MatSetOption - Sets a parameter option for a matrix. Some options
5737    may be specific to certain storage formats.  Some options
5738    determine how values will be inserted (or added). Sorted,
5739    row-oriented input will generally assemble the fastest. The default
5740    is row-oriented.
5741 
5742    Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5743 
5744    Input Parameters:
5745 +  mat - the matrix
5746 .  option - the option, one of those listed below (and possibly others),
5747 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5748 
5749   Options Describing Matrix Structure:
5750 +    `MAT_SPD` - symmetric positive definite
5751 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5752 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5753 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5754 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5755 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5756 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5757 
5758    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5759    do not need to be computed (usually at a high cost)
5760 
5761    Options For Use with `MatSetValues()`:
5762    Insert a logically dense subblock, which can be
5763 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5764 
5765    Note these options reflect the data you pass in with `MatSetValues()`; it has
5766    nothing to do with how the data is stored internally in the matrix
5767    data structure.
5768 
5769    When (re)assembling a matrix, we can restrict the input for
5770    efficiency/debugging purposes.  These options include
5771 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5772 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5773 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5774 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5775 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5776 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5777         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5778         performance for very large process counts.
5779 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5780         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5781         functions, instead sending only neighbor messages.
5782 
5783    Notes:
5784    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5785 
5786    Some options are relevant only for particular matrix types and
5787    are thus ignored by others.  Other options are not supported by
5788    certain matrix types and will generate an error message if set.
5789 
5790    If using a Fortran 77 module to compute a matrix, one may need to
5791    use the column-oriented option (or convert to the row-oriented
5792    format).
5793 
5794    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5795    that would generate a new entry in the nonzero structure is instead
5796    ignored.  Thus, if memory has not alredy been allocated for this particular
5797    data, then the insertion is ignored. For dense matrices, in which
5798    the entire array is allocated, no entries are ever ignored.
5799    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5800 
5801    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5802    that would generate a new entry in the nonzero structure instead produces
5803    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
5804 
5805    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5806    that would generate a new entry that has not been preallocated will
5807    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5808    only.) This is a useful flag when debugging matrix memory preallocation.
5809    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5810 
5811    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5812    other processors should be dropped, rather than stashed.
5813    This is useful if you know that the "owning" processor is also
5814    always generating the correct matrix entries, so that PETSc need
5815    not transfer duplicate entries generated on another processor.
5816 
5817    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5818    searches during matrix assembly. When this flag is set, the hash table
5819    is created during the first matrix assembly. This hash table is
5820    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5821    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5822    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5823    supported by` MATMPIBAIJ` format only.
5824 
5825    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5826    are kept in the nonzero structure
5827 
5828    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5829    a zero location in the matrix
5830 
5831    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5832 
5833    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5834         zero row routines and thus improves performance for very large process counts.
5835 
5836    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5837         part of the matrix (since they should match the upper triangular part).
5838 
5839    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5840                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5841                      with finite difference schemes with non-periodic boundary conditions.
5842 
5843    Developer Note:
5844    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5845    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5846    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5847    not changed.
5848 
5849    Level: intermediate
5850 
5851 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5852 @*/
5853 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5854 {
5855   PetscFunctionBegin;
5856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5857   if (op > 0) {
5858     PetscValidLogicalCollectiveEnum(mat, op, 2);
5859     PetscValidLogicalCollectiveBool(mat, flg, 3);
5860   }
5861 
5862   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);
5863 
5864   switch (op) {
5865   case MAT_FORCE_DIAGONAL_ENTRIES:
5866     mat->force_diagonals = flg;
5867     PetscFunctionReturn(0);
5868   case MAT_NO_OFF_PROC_ENTRIES:
5869     mat->nooffprocentries = flg;
5870     PetscFunctionReturn(0);
5871   case MAT_SUBSET_OFF_PROC_ENTRIES:
5872     mat->assembly_subset = flg;
5873     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5874 #if !defined(PETSC_HAVE_MPIUNI)
5875       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5876 #endif
5877       mat->stash.first_assembly_done = PETSC_FALSE;
5878     }
5879     PetscFunctionReturn(0);
5880   case MAT_NO_OFF_PROC_ZERO_ROWS:
5881     mat->nooffproczerorows = flg;
5882     PetscFunctionReturn(0);
5883   case MAT_SPD:
5884     if (flg) {
5885       mat->spd                    = PETSC_BOOL3_TRUE;
5886       mat->symmetric              = PETSC_BOOL3_TRUE;
5887       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5888     } else {
5889       mat->spd = PETSC_BOOL3_FALSE;
5890     }
5891     break;
5892   case MAT_SYMMETRIC:
5893     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5894     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5895 #if !defined(PETSC_USE_COMPLEX)
5896     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5897 #endif
5898     break;
5899   case MAT_HERMITIAN:
5900     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5901     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5902 #if !defined(PETSC_USE_COMPLEX)
5903     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5904 #endif
5905     break;
5906   case MAT_STRUCTURALLY_SYMMETRIC:
5907     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5908     break;
5909   case MAT_SYMMETRY_ETERNAL:
5910     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");
5911     mat->symmetry_eternal = flg;
5912     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5913     break;
5914   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5915     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");
5916     mat->structural_symmetry_eternal = flg;
5917     break;
5918   case MAT_SPD_ETERNAL:
5919     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");
5920     mat->spd_eternal = flg;
5921     if (flg) {
5922       mat->structural_symmetry_eternal = PETSC_TRUE;
5923       mat->symmetry_eternal            = PETSC_TRUE;
5924     }
5925     break;
5926   case MAT_STRUCTURE_ONLY:
5927     mat->structure_only = flg;
5928     break;
5929   case MAT_SORTED_FULL:
5930     mat->sortedfull = flg;
5931     break;
5932   default:
5933     break;
5934   }
5935   PetscTryTypeMethod(mat, setoption, op, flg);
5936   PetscFunctionReturn(0);
5937 }
5938 
5939 /*@
5940    MatGetOption - Gets a parameter option that has been set for a matrix.
5941 
5942    Logically Collective on mat
5943 
5944    Input Parameters:
5945 +  mat - the matrix
5946 -  option - the option, this only responds to certain options, check the code for which ones
5947 
5948    Output Parameter:
5949 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5950 
5951     Notes:
5952     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5953 
5954     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5955     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5956 
5957    Level: intermediate
5958 
5959 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5960     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5961 @*/
5962 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5963 {
5964   PetscFunctionBegin;
5965   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5966   PetscValidType(mat, 1);
5967 
5968   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);
5969   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()");
5970 
5971   switch (op) {
5972   case MAT_NO_OFF_PROC_ENTRIES:
5973     *flg = mat->nooffprocentries;
5974     break;
5975   case MAT_NO_OFF_PROC_ZERO_ROWS:
5976     *flg = mat->nooffproczerorows;
5977     break;
5978   case MAT_SYMMETRIC:
5979     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5980     break;
5981   case MAT_HERMITIAN:
5982     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5983     break;
5984   case MAT_STRUCTURALLY_SYMMETRIC:
5985     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5986     break;
5987   case MAT_SPD:
5988     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5989     break;
5990   case MAT_SYMMETRY_ETERNAL:
5991     *flg = mat->symmetry_eternal;
5992     break;
5993   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5994     *flg = mat->symmetry_eternal;
5995     break;
5996   default:
5997     break;
5998   }
5999   PetscFunctionReturn(0);
6000 }
6001 
6002 /*@
6003    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6004    this routine retains the old nonzero structure.
6005 
6006    Logically Collective on mat
6007 
6008    Input Parameters:
6009 .  mat - the matrix
6010 
6011    Level: intermediate
6012 
6013    Note:
6014     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.
6015    See the Performance chapter of the users manual for information on preallocating matrices.
6016 
6017 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6018 @*/
6019 PetscErrorCode MatZeroEntries(Mat mat)
6020 {
6021   PetscFunctionBegin;
6022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6023   PetscValidType(mat, 1);
6024   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6025   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");
6026   MatCheckPreallocated(mat, 1);
6027 
6028   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6029   PetscUseTypeMethod(mat, zeroentries);
6030   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6031   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6032   PetscFunctionReturn(0);
6033 }
6034 
6035 /*@
6036    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6037    of a set of rows and columns of a matrix.
6038 
6039    Collective on mat
6040 
6041    Input Parameters:
6042 +  mat - the matrix
6043 .  numRows - the number of rows to remove
6044 .  rows - the global row indices
6045 .  diag - value put in the diagonal of the eliminated rows
6046 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6047 -  b - optional vector of right hand side, that will be adjusted by provided solution
6048 
6049    Notes:
6050    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6051 
6052    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6053    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
6054 
6055    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6056    Krylov method to take advantage of the known solution on the zeroed rows.
6057 
6058    For the parallel case, all processes that share the matrix (i.e.,
6059    those in the communicator used for matrix creation) MUST call this
6060    routine, regardless of whether any rows being zeroed are owned by
6061    them.
6062 
6063    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6064 
6065    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6066    list only rows local to itself).
6067 
6068    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6069 
6070    Level: intermediate
6071 
6072 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6073           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6074 @*/
6075 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6076 {
6077   PetscFunctionBegin;
6078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6079   PetscValidType(mat, 1);
6080   if (numRows) PetscValidIntPointer(rows, 3);
6081   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6082   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6083   MatCheckPreallocated(mat, 1);
6084 
6085   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6086   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6087   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6088   PetscFunctionReturn(0);
6089 }
6090 
6091 /*@
6092    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6093    of a set of rows and columns of a matrix.
6094 
6095    Collective on mat
6096 
6097    Input Parameters:
6098 +  mat - the matrix
6099 .  is - the rows to zero
6100 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6101 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6102 -  b - optional vector of right hand side, that will be adjusted by provided solution
6103 
6104    Note:
6105    See `MatZeroRowsColumns()` for details on how this routine operates.
6106 
6107    Level: intermediate
6108 
6109 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6110           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6111 @*/
6112 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6113 {
6114   PetscInt        numRows;
6115   const PetscInt *rows;
6116 
6117   PetscFunctionBegin;
6118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6119   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6120   PetscValidType(mat, 1);
6121   PetscValidType(is, 2);
6122   PetscCall(ISGetLocalSize(is, &numRows));
6123   PetscCall(ISGetIndices(is, &rows));
6124   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6125   PetscCall(ISRestoreIndices(is, &rows));
6126   PetscFunctionReturn(0);
6127 }
6128 
6129 /*@
6130    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6131    of a set of rows of a matrix.
6132 
6133    Collective on mat
6134 
6135    Input Parameters:
6136 +  mat - the matrix
6137 .  numRows - the number of rows to remove
6138 .  rows - the global row indices
6139 .  diag - value put in the diagonal of the eliminated rows
6140 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6141 -  b - optional vector of right hand side, that will be adjusted by provided solution
6142 
6143    Notes:
6144    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6145 
6146    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6147 
6148    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6149    Krylov method to take advantage of the known solution on the zeroed rows.
6150 
6151    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6152    from the matrix.
6153 
6154    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6155    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
6156    formats this does not alter the nonzero structure.
6157 
6158    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6159    of the matrix is not changed the values are
6160    merely zeroed.
6161 
6162    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6163    formats can optionally remove the main diagonal entry from the
6164    nonzero structure as well, by passing 0.0 as the final argument).
6165 
6166    For the parallel case, all processes that share the matrix (i.e.,
6167    those in the communicator used for matrix creation) MUST call this
6168    routine, regardless of whether any rows being zeroed are owned by
6169    them.
6170 
6171    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6172    list only rows local to itself).
6173 
6174    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6175    owns that are to be zeroed. This saves a global synchronization in the implementation.
6176 
6177    Level: intermediate
6178 
6179 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6180           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6181 @*/
6182 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6183 {
6184   PetscFunctionBegin;
6185   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6186   PetscValidType(mat, 1);
6187   if (numRows) PetscValidIntPointer(rows, 3);
6188   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6189   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6190   MatCheckPreallocated(mat, 1);
6191 
6192   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6193   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6194   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6195   PetscFunctionReturn(0);
6196 }
6197 
6198 /*@
6199    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6200    of a set of rows of a matrix.
6201 
6202    Collective on Mat
6203 
6204    Input Parameters:
6205 +  mat - the matrix
6206 .  is - index set of rows to remove (if NULL then no row is removed)
6207 .  diag - value put in all diagonals of eliminated rows
6208 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6209 -  b - optional vector of right hand side, that will be adjusted by provided solution
6210 
6211    Note:
6212    See `MatZeroRows()` for details on how this routine operates.
6213 
6214    Level: intermediate
6215 
6216 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6217           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6218 @*/
6219 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6220 {
6221   PetscInt        numRows = 0;
6222   const PetscInt *rows    = NULL;
6223 
6224   PetscFunctionBegin;
6225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6226   PetscValidType(mat, 1);
6227   if (is) {
6228     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6229     PetscCall(ISGetLocalSize(is, &numRows));
6230     PetscCall(ISGetIndices(is, &rows));
6231   }
6232   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6233   if (is) PetscCall(ISRestoreIndices(is, &rows));
6234   PetscFunctionReturn(0);
6235 }
6236 
6237 /*@
6238    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6239    of a set of rows of a matrix. These rows must be local to the process.
6240 
6241    Collective on mat
6242 
6243    Input Parameters:
6244 +  mat - the matrix
6245 .  numRows - the number of rows to remove
6246 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6247 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6248 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6249 -  b - optional vector of right hand side, that will be adjusted by provided solution
6250 
6251    Notes:
6252    See `MatZeroRows()` for details on how this routine operates.
6253 
6254    The grid coordinates are across the entire grid, not just the local portion
6255 
6256    In Fortran idxm and idxn should be declared as
6257 $     MatStencil idxm(4,m)
6258    and the values inserted using
6259 $    idxm(MatStencil_i,1) = i
6260 $    idxm(MatStencil_j,1) = j
6261 $    idxm(MatStencil_k,1) = k
6262 $    idxm(MatStencil_c,1) = c
6263    etc
6264 
6265    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6266    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6267    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6268    `DM_BOUNDARY_PERIODIC` boundary type.
6269 
6270    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
6271    a single value per point) you can skip filling those indices.
6272 
6273    Level: intermediate
6274 
6275 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6276           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6277 @*/
6278 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6279 {
6280   PetscInt  dim    = mat->stencil.dim;
6281   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6282   PetscInt *dims   = mat->stencil.dims + 1;
6283   PetscInt *starts = mat->stencil.starts;
6284   PetscInt *dxm    = (PetscInt *)rows;
6285   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6286 
6287   PetscFunctionBegin;
6288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6289   PetscValidType(mat, 1);
6290   if (numRows) PetscValidPointer(rows, 3);
6291 
6292   PetscCall(PetscMalloc1(numRows, &jdxm));
6293   for (i = 0; i < numRows; ++i) {
6294     /* Skip unused dimensions (they are ordered k, j, i, c) */
6295     for (j = 0; j < 3 - sdim; ++j) dxm++;
6296     /* Local index in X dir */
6297     tmp = *dxm++ - starts[0];
6298     /* Loop over remaining dimensions */
6299     for (j = 0; j < dim - 1; ++j) {
6300       /* If nonlocal, set index to be negative */
6301       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6302       /* Update local index */
6303       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6304     }
6305     /* Skip component slot if necessary */
6306     if (mat->stencil.noc) dxm++;
6307     /* Local row number */
6308     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6309   }
6310   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6311   PetscCall(PetscFree(jdxm));
6312   PetscFunctionReturn(0);
6313 }
6314 
6315 /*@
6316    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6317    of a set of rows and columns of a matrix.
6318 
6319    Collective on mat
6320 
6321    Input Parameters:
6322 +  mat - the matrix
6323 .  numRows - the number of rows/columns to remove
6324 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6325 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6326 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6327 -  b - optional vector of right hand side, that will be adjusted by provided solution
6328 
6329    Notes:
6330    See `MatZeroRowsColumns()` for details on how this routine operates.
6331 
6332    The grid coordinates are across the entire grid, not just the local portion
6333 
6334    In Fortran idxm and idxn should be declared as
6335 $     MatStencil idxm(4,m)
6336    and the values inserted using
6337 $    idxm(MatStencil_i,1) = i
6338 $    idxm(MatStencil_j,1) = j
6339 $    idxm(MatStencil_k,1) = k
6340 $    idxm(MatStencil_c,1) = c
6341    etc
6342 
6343    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6344    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6345    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6346    `DM_BOUNDARY_PERIODIC` boundary type.
6347 
6348    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
6349    a single value per point) you can skip filling those indices.
6350 
6351    Level: intermediate
6352 
6353 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6354           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6355 @*/
6356 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6357 {
6358   PetscInt  dim    = mat->stencil.dim;
6359   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6360   PetscInt *dims   = mat->stencil.dims + 1;
6361   PetscInt *starts = mat->stencil.starts;
6362   PetscInt *dxm    = (PetscInt *)rows;
6363   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6364 
6365   PetscFunctionBegin;
6366   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6367   PetscValidType(mat, 1);
6368   if (numRows) PetscValidPointer(rows, 3);
6369 
6370   PetscCall(PetscMalloc1(numRows, &jdxm));
6371   for (i = 0; i < numRows; ++i) {
6372     /* Skip unused dimensions (they are ordered k, j, i, c) */
6373     for (j = 0; j < 3 - sdim; ++j) dxm++;
6374     /* Local index in X dir */
6375     tmp = *dxm++ - starts[0];
6376     /* Loop over remaining dimensions */
6377     for (j = 0; j < dim - 1; ++j) {
6378       /* If nonlocal, set index to be negative */
6379       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6380       /* Update local index */
6381       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6382     }
6383     /* Skip component slot if necessary */
6384     if (mat->stencil.noc) dxm++;
6385     /* Local row number */
6386     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6387   }
6388   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6389   PetscCall(PetscFree(jdxm));
6390   PetscFunctionReturn(0);
6391 }
6392 
6393 /*@C
6394    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6395    of a set of rows of a matrix; using local numbering of rows.
6396 
6397    Collective on mat
6398 
6399    Input Parameters:
6400 +  mat - the matrix
6401 .  numRows - the number of rows to remove
6402 .  rows - the local row indices
6403 .  diag - value put in all diagonals of eliminated rows
6404 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6405 -  b - optional vector of right hand side, that will be adjusted by provided solution
6406 
6407    Notes:
6408    Before calling `MatZeroRowsLocal()`, the user must first set the
6409    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6410 
6411    See `MatZeroRows()` for details on how this routine operates.
6412 
6413    Level: intermediate
6414 
6415 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6416           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6417 @*/
6418 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6419 {
6420   PetscFunctionBegin;
6421   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6422   PetscValidType(mat, 1);
6423   if (numRows) PetscValidIntPointer(rows, 3);
6424   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6425   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6426   MatCheckPreallocated(mat, 1);
6427 
6428   if (mat->ops->zerorowslocal) {
6429     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6430   } else {
6431     IS              is, newis;
6432     const PetscInt *newRows;
6433 
6434     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6435     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6436     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6437     PetscCall(ISGetIndices(newis, &newRows));
6438     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6439     PetscCall(ISRestoreIndices(newis, &newRows));
6440     PetscCall(ISDestroy(&newis));
6441     PetscCall(ISDestroy(&is));
6442   }
6443   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6444   PetscFunctionReturn(0);
6445 }
6446 
6447 /*@
6448    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6449    of a set of rows of a matrix; using local numbering of rows.
6450 
6451    Collective on mat
6452 
6453    Input Parameters:
6454 +  mat - the matrix
6455 .  is - index set of rows to remove
6456 .  diag - value put in all diagonals of eliminated rows
6457 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6458 -  b - optional vector of right hand side, that will be adjusted by provided solution
6459 
6460    Notes:
6461    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6462    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6463 
6464    See `MatZeroRows()` for details on how this routine operates.
6465 
6466    Level: intermediate
6467 
6468 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6469           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6470 @*/
6471 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6472 {
6473   PetscInt        numRows;
6474   const PetscInt *rows;
6475 
6476   PetscFunctionBegin;
6477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6478   PetscValidType(mat, 1);
6479   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6480   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6481   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6482   MatCheckPreallocated(mat, 1);
6483 
6484   PetscCall(ISGetLocalSize(is, &numRows));
6485   PetscCall(ISGetIndices(is, &rows));
6486   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6487   PetscCall(ISRestoreIndices(is, &rows));
6488   PetscFunctionReturn(0);
6489 }
6490 
6491 /*@
6492    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6493    of a set of rows and columns of a matrix; using local numbering of rows.
6494 
6495    Collective on mat
6496 
6497    Input Parameters:
6498 +  mat - the matrix
6499 .  numRows - the number of rows to remove
6500 .  rows - the global row indices
6501 .  diag - value put in all diagonals of eliminated rows
6502 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6503 -  b - optional vector of right hand side, that will be adjusted by provided solution
6504 
6505    Notes:
6506    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6507    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6508 
6509    See `MatZeroRowsColumns()` for details on how this routine operates.
6510 
6511    Level: intermediate
6512 
6513 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6514           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6515 @*/
6516 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6517 {
6518   IS              is, newis;
6519   const PetscInt *newRows;
6520 
6521   PetscFunctionBegin;
6522   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6523   PetscValidType(mat, 1);
6524   if (numRows) PetscValidIntPointer(rows, 3);
6525   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6526   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6527   MatCheckPreallocated(mat, 1);
6528 
6529   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6530   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6531   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6532   PetscCall(ISGetIndices(newis, &newRows));
6533   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6534   PetscCall(ISRestoreIndices(newis, &newRows));
6535   PetscCall(ISDestroy(&newis));
6536   PetscCall(ISDestroy(&is));
6537   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6538   PetscFunctionReturn(0);
6539 }
6540 
6541 /*@
6542    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6543    of a set of rows and columns of a matrix; using local numbering of rows.
6544 
6545    Collective on Mat
6546 
6547    Input Parameters:
6548 +  mat - the matrix
6549 .  is - index set of rows to remove
6550 .  diag - value put in all diagonals of eliminated rows
6551 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6552 -  b - optional vector of right hand side, that will be adjusted by provided solution
6553 
6554    Notes:
6555    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6556    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6557 
6558    See `MatZeroRowsColumns()` for details on how this routine operates.
6559 
6560    Level: intermediate
6561 
6562 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6563           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6564 @*/
6565 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6566 {
6567   PetscInt        numRows;
6568   const PetscInt *rows;
6569 
6570   PetscFunctionBegin;
6571   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6572   PetscValidType(mat, 1);
6573   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6574   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6575   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6576   MatCheckPreallocated(mat, 1);
6577 
6578   PetscCall(ISGetLocalSize(is, &numRows));
6579   PetscCall(ISGetIndices(is, &rows));
6580   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6581   PetscCall(ISRestoreIndices(is, &rows));
6582   PetscFunctionReturn(0);
6583 }
6584 
6585 /*@C
6586    MatGetSize - Returns the numbers of rows and columns in a matrix.
6587 
6588    Not Collective
6589 
6590    Input Parameter:
6591 .  mat - the matrix
6592 
6593    Output Parameters:
6594 +  m - the number of global rows
6595 -  n - the number of global columns
6596 
6597    Note: both output parameters can be NULL on input.
6598 
6599    Level: beginner
6600 
6601 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6602 @*/
6603 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6604 {
6605   PetscFunctionBegin;
6606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6607   if (m) *m = mat->rmap->N;
6608   if (n) *n = mat->cmap->N;
6609   PetscFunctionReturn(0);
6610 }
6611 
6612 /*@C
6613    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6614    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6615 
6616    Not Collective
6617 
6618    Input Parameter:
6619 .  mat - the matrix
6620 
6621    Output Parameters:
6622 +  m - the number of local rows, use `NULL` to not obtain this value
6623 -  n - the number of local columns, use `NULL` to not obtain this value
6624 
6625    Level: beginner
6626 
6627 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6628 @*/
6629 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6630 {
6631   PetscFunctionBegin;
6632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6633   if (m) PetscValidIntPointer(m, 2);
6634   if (n) PetscValidIntPointer(n, 3);
6635   if (m) *m = mat->rmap->n;
6636   if (n) *n = mat->cmap->n;
6637   PetscFunctionReturn(0);
6638 }
6639 
6640 /*@C
6641    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6642    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6643 
6644    Not Collective, unless matrix has not been allocated, then collective on mat
6645 
6646    Input Parameter:
6647 .  mat - the matrix
6648 
6649    Output Parameters:
6650 +  m - the global index of the first local column, use `NULL` to not obtain this value
6651 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6652 
6653    Level: developer
6654 
6655 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6656 @*/
6657 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6658 {
6659   PetscFunctionBegin;
6660   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6661   PetscValidType(mat, 1);
6662   if (m) PetscValidIntPointer(m, 2);
6663   if (n) PetscValidIntPointer(n, 3);
6664   MatCheckPreallocated(mat, 1);
6665   if (m) *m = mat->cmap->rstart;
6666   if (n) *n = mat->cmap->rend;
6667   PetscFunctionReturn(0);
6668 }
6669 
6670 /*@C
6671    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6672    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
6673    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6674 
6675    Not Collective
6676 
6677    Input Parameter:
6678 .  mat - the matrix
6679 
6680    Output Parameters:
6681 +  m - the global index of the first local row, use `NULL` to not obtain this value
6682 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6683 
6684    Note:
6685   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6686   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6687   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6688 
6689    Level: beginner
6690 
6691 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6692           `PetscLayout`
6693 @*/
6694 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6695 {
6696   PetscFunctionBegin;
6697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6698   PetscValidType(mat, 1);
6699   if (m) PetscValidIntPointer(m, 2);
6700   if (n) PetscValidIntPointer(n, 3);
6701   MatCheckPreallocated(mat, 1);
6702   if (m) *m = mat->rmap->rstart;
6703   if (n) *n = mat->rmap->rend;
6704   PetscFunctionReturn(0);
6705 }
6706 
6707 /*@C
6708    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6709    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
6710    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6711 
6712    Not Collective, unless matrix has not been allocated, then collective on mat
6713 
6714    Input Parameters:
6715 .  mat - the matrix
6716 
6717    Output Parameters:
6718 .  ranges - start of each processors portion plus one more than the total length at the end
6719 
6720    Level: beginner
6721 
6722 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6723 @*/
6724 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6725 {
6726   PetscFunctionBegin;
6727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6728   PetscValidType(mat, 1);
6729   MatCheckPreallocated(mat, 1);
6730   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6731   PetscFunctionReturn(0);
6732 }
6733 
6734 /*@C
6735    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6736    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6737 
6738    Not Collective, unless matrix has not been allocated, then collective on Mat
6739 
6740    Input Parameters:
6741 .  mat - the matrix
6742 
6743    Output Parameters:
6744 .  ranges - start of each processors portion plus one more then the total length at the end
6745 
6746    Level: beginner
6747 
6748 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6749 @*/
6750 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6751 {
6752   PetscFunctionBegin;
6753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6754   PetscValidType(mat, 1);
6755   MatCheckPreallocated(mat, 1);
6756   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6757   PetscFunctionReturn(0);
6758 }
6759 
6760 /*@C
6761    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6762    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6763    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6764 
6765    Not Collective
6766 
6767    Input Parameter:
6768 .  A - matrix
6769 
6770    Output Parameters:
6771 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6772 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6773 
6774    Level: intermediate
6775 
6776 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6777 @*/
6778 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6779 {
6780   PetscErrorCode (*f)(Mat, IS *, IS *);
6781 
6782   PetscFunctionBegin;
6783   MatCheckPreallocated(A, 1);
6784   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6785   if (f) {
6786     PetscCall((*f)(A, rows, cols));
6787   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6788     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6789     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6790   }
6791   PetscFunctionReturn(0);
6792 }
6793 
6794 /*@C
6795    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6796    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6797    to complete the factorization.
6798 
6799    Collective on fact
6800 
6801    Input Parameters:
6802 +  fact - the factorized matrix obtained with `MatGetFactor()`
6803 .  mat - the matrix
6804 .  row - row permutation
6805 .  column - column permutation
6806 -  info - structure containing
6807 $      levels - number of levels of fill.
6808 $      expected fill - as ratio of original fill.
6809 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6810                 missing diagonal entries)
6811 
6812    Output Parameters:
6813 .  fact - new matrix that has been symbolically factored
6814 
6815    Level: developer
6816 
6817    Notes:
6818    See [Matrix Factorization](sec_matfactor) for additional information.
6819 
6820    Most users should employ the `KSP` interface for linear solvers
6821    instead of working directly with matrix algebra routines such as this.
6822    See, e.g., `KSPCreate()`.
6823 
6824    Uses the definition of level of fill as in Y. Saad, 2003
6825 
6826    Developer Note:
6827    The Fortran interface is not autogenerated as the f90
6828    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6829 
6830    References:
6831 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6832 
6833 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6834           `MatGetOrdering()`, `MatFactorInfo`
6835 @*/
6836 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6837 {
6838   PetscFunctionBegin;
6839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6840   PetscValidType(mat, 2);
6841   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6842   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6843   PetscValidPointer(info, 5);
6844   PetscValidPointer(fact, 1);
6845   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6846   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6847   if (!fact->ops->ilufactorsymbolic) {
6848     MatSolverType stype;
6849     PetscCall(MatFactorGetSolverType(fact, &stype));
6850     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6851   }
6852   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6853   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6854   MatCheckPreallocated(mat, 2);
6855 
6856   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6857   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6858   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6859   PetscFunctionReturn(0);
6860 }
6861 
6862 /*@C
6863    MatICCFactorSymbolic - Performs symbolic incomplete
6864    Cholesky factorization for a symmetric matrix.  Use
6865    `MatCholeskyFactorNumeric()` to complete the factorization.
6866 
6867    Collective on fact
6868 
6869    Input Parameters:
6870 +  fact - the factorized matrix obtained with `MatGetFactor()`
6871 .  mat - the matrix to be factored
6872 .  perm - row and column permutation
6873 -  info - structure containing
6874 $      levels - number of levels of fill.
6875 $      expected fill - as ratio of original fill.
6876 
6877    Output Parameter:
6878 .  fact - the factored matrix
6879 
6880    Level: developer
6881 
6882    Notes:
6883    Most users should employ the `KSP` interface for linear solvers
6884    instead of working directly with matrix algebra routines such as this.
6885    See, e.g., `KSPCreate()`.
6886 
6887    This uses the definition of level of fill as in Y. Saad, 2003
6888 
6889    Developer Note:
6890    The Fortran interface is not autogenerated as the f90
6891    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6892 
6893    References:
6894 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6895 
6896 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6897 @*/
6898 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6899 {
6900   PetscFunctionBegin;
6901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6902   PetscValidType(mat, 2);
6903   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6904   PetscValidPointer(info, 4);
6905   PetscValidPointer(fact, 1);
6906   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6907   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6908   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6909   if (!(fact)->ops->iccfactorsymbolic) {
6910     MatSolverType stype;
6911     PetscCall(MatFactorGetSolverType(fact, &stype));
6912     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6913   }
6914   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6915   MatCheckPreallocated(mat, 2);
6916 
6917   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6918   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6919   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6920   PetscFunctionReturn(0);
6921 }
6922 
6923 /*@C
6924    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6925    points to an array of valid matrices, they may be reused to store the new
6926    submatrices.
6927 
6928    Collective on mat
6929 
6930    Input Parameters:
6931 +  mat - the matrix
6932 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6933 .  irow, icol - index sets of rows and columns to extract
6934 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6935 
6936    Output Parameter:
6937 .  submat - the array of submatrices
6938 
6939    Notes:
6940    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6941    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6942    to extract a parallel submatrix.
6943 
6944    Some matrix types place restrictions on the row and column
6945    indices, such as that they be sorted or that they be equal to each other.
6946 
6947    The index sets may not have duplicate entries.
6948 
6949    When extracting submatrices from a parallel matrix, each processor can
6950    form a different submatrix by setting the rows and columns of its
6951    individual index sets according to the local submatrix desired.
6952 
6953    When finished using the submatrices, the user should destroy
6954    them with `MatDestroySubMatrices()`.
6955 
6956    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6957    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6958 
6959    This routine creates the matrices in submat; you should NOT create them before
6960    calling it. It also allocates the array of matrix pointers submat.
6961 
6962    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6963    request one row/column in a block, they must request all rows/columns that are in
6964    that block. For example, if the block size is 2 you cannot request just row 0 and
6965    column 0.
6966 
6967    Fortran Note:
6968    The Fortran interface is slightly different from that given below; it
6969    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
6970 
6971    Level: advanced
6972 
6973 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6974 @*/
6975 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6976 {
6977   PetscInt  i;
6978   PetscBool eq;
6979 
6980   PetscFunctionBegin;
6981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6982   PetscValidType(mat, 1);
6983   if (n) {
6984     PetscValidPointer(irow, 3);
6985     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6986     PetscValidPointer(icol, 4);
6987     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6988   }
6989   PetscValidPointer(submat, 6);
6990   if (n && scall == MAT_REUSE_MATRIX) {
6991     PetscValidPointer(*submat, 6);
6992     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
6993   }
6994   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6995   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6996   MatCheckPreallocated(mat, 1);
6997   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6998   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6999   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7000   for (i = 0; i < n; i++) {
7001     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7002     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7003     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7004 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7005     if (mat->boundtocpu && mat->bindingpropagates) {
7006       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7007       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7008     }
7009 #endif
7010   }
7011   PetscFunctionReturn(0);
7012 }
7013 
7014 /*@C
7015    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7016 
7017    Collective on mat
7018 
7019    Input Parameters:
7020 +  mat - the matrix
7021 .  n   - the number of submatrixes to be extracted
7022 .  irow, icol - index sets of rows and columns to extract
7023 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7024 
7025    Output Parameter:
7026 .  submat - the array of submatrices
7027 
7028    Level: advanced
7029 
7030    Note:
7031    This is used by `PCGASM`
7032 
7033 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7034 @*/
7035 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7036 {
7037   PetscInt  i;
7038   PetscBool eq;
7039 
7040   PetscFunctionBegin;
7041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7042   PetscValidType(mat, 1);
7043   if (n) {
7044     PetscValidPointer(irow, 3);
7045     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7046     PetscValidPointer(icol, 4);
7047     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7048   }
7049   PetscValidPointer(submat, 6);
7050   if (n && scall == MAT_REUSE_MATRIX) {
7051     PetscValidPointer(*submat, 6);
7052     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7053   }
7054   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7055   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7056   MatCheckPreallocated(mat, 1);
7057 
7058   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7059   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7060   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7061   for (i = 0; i < n; i++) {
7062     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7063     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7064   }
7065   PetscFunctionReturn(0);
7066 }
7067 
7068 /*@C
7069    MatDestroyMatrices - Destroys an array of matrices.
7070 
7071    Collective on mat
7072 
7073    Input Parameters:
7074 +  n - the number of local matrices
7075 -  mat - the matrices (note that this is a pointer to the array of matrices)
7076 
7077    Level: advanced
7078 
7079     Note:
7080     Frees not only the matrices, but also the array that contains the matrices
7081            In Fortran will not free the array.
7082 
7083 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7084 @*/
7085 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7086 {
7087   PetscInt i;
7088 
7089   PetscFunctionBegin;
7090   if (!*mat) PetscFunctionReturn(0);
7091   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7092   PetscValidPointer(mat, 2);
7093 
7094   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7095 
7096   /* memory is allocated even if n = 0 */
7097   PetscCall(PetscFree(*mat));
7098   PetscFunctionReturn(0);
7099 }
7100 
7101 /*@C
7102    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7103 
7104    Collective on mat
7105 
7106    Input Parameters:
7107 +  n - the number of local matrices
7108 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7109                        sequence of MatCreateSubMatrices())
7110 
7111    Level: advanced
7112 
7113     Note:
7114     Frees not only the matrices, but also the array that contains the matrices
7115            In Fortran will not free the array.
7116 
7117 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7118 @*/
7119 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7120 {
7121   Mat mat0;
7122 
7123   PetscFunctionBegin;
7124   if (!*mat) PetscFunctionReturn(0);
7125   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7126   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7127   PetscValidPointer(mat, 2);
7128 
7129   mat0 = (*mat)[0];
7130   if (mat0 && mat0->ops->destroysubmatrices) {
7131     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7132   } else {
7133     PetscCall(MatDestroyMatrices(n, mat));
7134   }
7135   PetscFunctionReturn(0);
7136 }
7137 
7138 /*@C
7139    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7140 
7141    Collective on mat
7142 
7143    Input Parameters:
7144 .  mat - the matrix
7145 
7146    Output Parameter:
7147 .  matstruct - the sequential matrix with the nonzero structure of mat
7148 
7149   Level: developer
7150 
7151 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7152 @*/
7153 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7154 {
7155   PetscFunctionBegin;
7156   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7157   PetscValidPointer(matstruct, 2);
7158 
7159   PetscValidType(mat, 1);
7160   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7161   MatCheckPreallocated(mat, 1);
7162 
7163   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7164   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7165   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7166   PetscFunctionReturn(0);
7167 }
7168 
7169 /*@C
7170    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7171 
7172    Collective on mat
7173 
7174    Input Parameters:
7175 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7176                        sequence of `MatGetSequentialNonzeroStructure()`)
7177 
7178    Level: advanced
7179 
7180     Note:
7181     Frees not only the matrices, but also the array that contains the matrices
7182 
7183 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7184 @*/
7185 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7186 {
7187   PetscFunctionBegin;
7188   PetscValidPointer(mat, 1);
7189   PetscCall(MatDestroy(mat));
7190   PetscFunctionReturn(0);
7191 }
7192 
7193 /*@
7194    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7195    replaces the index sets by larger ones that represent submatrices with
7196    additional overlap.
7197 
7198    Collective on mat
7199 
7200    Input Parameters:
7201 +  mat - the matrix
7202 .  n   - the number of index sets
7203 .  is  - the array of index sets (these index sets will changed during the call)
7204 -  ov  - the additional overlap requested
7205 
7206    Options Database:
7207 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7208 
7209    Level: developer
7210 
7211    Developer Note:
7212    Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.
7213 
7214 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7215 @*/
7216 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7217 {
7218   PetscInt i, bs, cbs;
7219 
7220   PetscFunctionBegin;
7221   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7222   PetscValidType(mat, 1);
7223   PetscValidLogicalCollectiveInt(mat, n, 2);
7224   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7225   if (n) {
7226     PetscValidPointer(is, 3);
7227     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7228   }
7229   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7230   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7231   MatCheckPreallocated(mat, 1);
7232 
7233   if (!ov || !n) PetscFunctionReturn(0);
7234   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7235   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7236   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7237   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7238   if (bs == cbs) {
7239     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7240   }
7241   PetscFunctionReturn(0);
7242 }
7243 
7244 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7245 
7246 /*@
7247    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7248    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7249    additional overlap.
7250 
7251    Collective on mat
7252 
7253    Input Parameters:
7254 +  mat - the matrix
7255 .  n   - the number of index sets
7256 .  is  - the array of index sets (these index sets will changed during the call)
7257 -  ov  - the additional overlap requested
7258 
7259 `   Options Database:
7260 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7261 
7262    Level: developer
7263 
7264 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7265 @*/
7266 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7267 {
7268   PetscInt i;
7269 
7270   PetscFunctionBegin;
7271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7272   PetscValidType(mat, 1);
7273   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7274   if (n) {
7275     PetscValidPointer(is, 3);
7276     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7277   }
7278   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7279   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7280   MatCheckPreallocated(mat, 1);
7281   if (!ov) PetscFunctionReturn(0);
7282   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7283   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7284   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7285   PetscFunctionReturn(0);
7286 }
7287 
7288 /*@
7289    MatGetBlockSize - Returns the matrix block size.
7290 
7291    Not Collective
7292 
7293    Input Parameter:
7294 .  mat - the matrix
7295 
7296    Output Parameter:
7297 .  bs - block size
7298 
7299    Notes:
7300     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7301 
7302    If the block size has not been set yet this routine returns 1.
7303 
7304    Level: intermediate
7305 
7306 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7307 @*/
7308 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7309 {
7310   PetscFunctionBegin;
7311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7312   PetscValidIntPointer(bs, 2);
7313   *bs = PetscAbs(mat->rmap->bs);
7314   PetscFunctionReturn(0);
7315 }
7316 
7317 /*@
7318    MatGetBlockSizes - Returns the matrix block row and column sizes.
7319 
7320    Not Collective
7321 
7322    Input Parameter:
7323 .  mat - the matrix
7324 
7325    Output Parameters:
7326 +  rbs - row block size
7327 -  cbs - column block size
7328 
7329    Notes:
7330     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7331     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7332 
7333    If a block size has not been set yet this routine returns 1.
7334 
7335    Level: intermediate
7336 
7337 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7338 @*/
7339 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7340 {
7341   PetscFunctionBegin;
7342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7343   if (rbs) PetscValidIntPointer(rbs, 2);
7344   if (cbs) PetscValidIntPointer(cbs, 3);
7345   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7346   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7347   PetscFunctionReturn(0);
7348 }
7349 
7350 /*@
7351    MatSetBlockSize - Sets the matrix block size.
7352 
7353    Logically Collective on mat
7354 
7355    Input Parameters:
7356 +  mat - the matrix
7357 -  bs - block size
7358 
7359    Notes:
7360     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7361     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7362 
7363     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7364     is compatible with the matrix local sizes.
7365 
7366    Level: intermediate
7367 
7368 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7369 @*/
7370 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7371 {
7372   PetscFunctionBegin;
7373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7374   PetscValidLogicalCollectiveInt(mat, bs, 2);
7375   PetscCall(MatSetBlockSizes(mat, bs, bs));
7376   PetscFunctionReturn(0);
7377 }
7378 
7379 typedef struct {
7380   PetscInt         n;
7381   IS              *is;
7382   Mat             *mat;
7383   PetscObjectState nonzerostate;
7384   Mat              C;
7385 } EnvelopeData;
7386 
7387 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7388 {
7389   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7390   PetscCall(PetscFree(edata->is));
7391   PetscCall(PetscFree(edata));
7392   return 0;
7393 }
7394 
7395 /*
7396    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7397          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7398 
7399    Collective on mat
7400 
7401    Input Parameter:
7402 .  mat - the matrix
7403 
7404    Notes:
7405      There can be zeros within the blocks
7406 
7407      The blocks can overlap between processes, including laying on more than two processes
7408 
7409 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7410 */
7411 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7412 {
7413   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7414   PetscInt          *diag, *odiag, sc;
7415   VecScatter         scatter;
7416   PetscScalar       *seqv;
7417   const PetscScalar *parv;
7418   const PetscInt    *ia, *ja;
7419   PetscBool          set, flag, done;
7420   Mat                AA = mat, A;
7421   MPI_Comm           comm;
7422   PetscMPIInt        rank, size, tag;
7423   MPI_Status         status;
7424   PetscContainer     container;
7425   EnvelopeData      *edata;
7426   Vec                seq, par;
7427   IS                 isglobal;
7428 
7429   PetscFunctionBegin;
7430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7431   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7432   if (!set || !flag) {
7433     /* TOO: only needs nonzero structure of transpose */
7434     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7435     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7436   }
7437   PetscCall(MatAIJGetLocalMat(AA, &A));
7438   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7439   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7440 
7441   PetscCall(MatGetLocalSize(mat, &n, NULL));
7442   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7443   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7444   PetscCallMPI(MPI_Comm_size(comm, &size));
7445   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7446 
7447   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7448 
7449   if (rank > 0) {
7450     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7451     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7452   }
7453   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7454   for (i = 0; i < n; i++) {
7455     env = PetscMax(env, ja[ia[i + 1] - 1]);
7456     II  = rstart + i;
7457     if (env == II) {
7458       starts[lblocks]  = tbs;
7459       sizes[lblocks++] = 1 + II - tbs;
7460       tbs              = 1 + II;
7461     }
7462   }
7463   if (rank < size - 1) {
7464     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7465     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7466   }
7467 
7468   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7469   if (!set || !flag) PetscCall(MatDestroy(&AA));
7470   PetscCall(MatDestroy(&A));
7471 
7472   PetscCall(PetscNew(&edata));
7473   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7474   edata->n = lblocks;
7475   /* create IS needed for extracting blocks from the original matrix */
7476   PetscCall(PetscMalloc1(lblocks, &edata->is));
7477   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7478 
7479   /* Create the resulting inverse matrix structure with preallocation information */
7480   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7481   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7482   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7483   PetscCall(MatSetType(edata->C, MATAIJ));
7484 
7485   /* Communicate the start and end of each row, from each block to the correct rank */
7486   /* TODO: Use PetscSF instead of VecScatter */
7487   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7488   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7489   PetscCall(VecGetArrayWrite(seq, &seqv));
7490   for (PetscInt i = 0; i < lblocks; i++) {
7491     for (PetscInt j = 0; j < sizes[i]; j++) {
7492       seqv[cnt]     = starts[i];
7493       seqv[cnt + 1] = starts[i] + sizes[i];
7494       cnt += 2;
7495     }
7496   }
7497   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7498   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7499   sc -= cnt;
7500   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7501   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7502   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7503   PetscCall(ISDestroy(&isglobal));
7504   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7505   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7506   PetscCall(VecScatterDestroy(&scatter));
7507   PetscCall(VecDestroy(&seq));
7508   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7509   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7510   PetscCall(VecGetArrayRead(par, &parv));
7511   cnt = 0;
7512   PetscCall(MatGetSize(mat, NULL, &n));
7513   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7514     PetscInt start, end, d = 0, od = 0;
7515 
7516     start = (PetscInt)PetscRealPart(parv[cnt]);
7517     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7518     cnt += 2;
7519 
7520     if (start < cstart) {
7521       od += cstart - start + n - cend;
7522       d += cend - cstart;
7523     } else if (start < cend) {
7524       od += n - cend;
7525       d += cend - start;
7526     } else od += n - start;
7527     if (end <= cstart) {
7528       od -= cstart - end + n - cend;
7529       d -= cend - cstart;
7530     } else if (end < cend) {
7531       od -= n - cend;
7532       d -= cend - end;
7533     } else od -= n - end;
7534 
7535     odiag[i] = od;
7536     diag[i]  = d;
7537   }
7538   PetscCall(VecRestoreArrayRead(par, &parv));
7539   PetscCall(VecDestroy(&par));
7540   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7541   PetscCall(PetscFree2(diag, odiag));
7542   PetscCall(PetscFree2(sizes, starts));
7543 
7544   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7545   PetscCall(PetscContainerSetPointer(container, edata));
7546   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7547   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7548   PetscCall(PetscObjectDereference((PetscObject)container));
7549   PetscFunctionReturn(0);
7550 }
7551 
7552 /*@
7553   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7554 
7555   Collective on A
7556 
7557   Input Parameters:
7558 . A - the matrix
7559 
7560   Output Parameters:
7561 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7562 
7563   Note:
7564      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7565 
7566   Level: advanced
7567 
7568 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7569 @*/
7570 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7571 {
7572   PetscContainer   container;
7573   EnvelopeData    *edata;
7574   PetscObjectState nonzerostate;
7575 
7576   PetscFunctionBegin;
7577   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7578   if (!container) {
7579     PetscCall(MatComputeVariableBlockEnvelope(A));
7580     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7581   }
7582   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7583   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7584   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7585   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7586 
7587   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7588   *C = edata->C;
7589 
7590   for (PetscInt i = 0; i < edata->n; i++) {
7591     Mat          D;
7592     PetscScalar *dvalues;
7593 
7594     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7595     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7596     PetscCall(MatSeqDenseInvert(D));
7597     PetscCall(MatDenseGetArray(D, &dvalues));
7598     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7599     PetscCall(MatDestroy(&D));
7600   }
7601   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7602   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7603   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7604   PetscFunctionReturn(0);
7605 }
7606 
7607 /*@
7608    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7609 
7610    Logically Collective on mat
7611 
7612    Input Parameters:
7613 +  mat - the matrix
7614 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7615 -  bsizes - the block sizes
7616 
7617    Notes:
7618     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7619 
7620     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.
7621 
7622    Level: intermediate
7623 
7624 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7625           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7626 @*/
7627 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7628 {
7629   PetscInt i, ncnt = 0, nlocal;
7630 
7631   PetscFunctionBegin;
7632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7633   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7634   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7635   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7636   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);
7637   PetscCall(PetscFree(mat->bsizes));
7638   mat->nblocks = nblocks;
7639   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7640   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7641   PetscFunctionReturn(0);
7642 }
7643 
7644 /*@C
7645    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7646 
7647    Logically Collective on mat
7648 
7649    Input Parameter:
7650 .  mat - the matrix
7651 
7652    Output Parameters:
7653 +  nblocks - the number of blocks on this process
7654 -  bsizes - the block sizes
7655 
7656    Fortran Note:
7657    Currently not supported from Fortran
7658 
7659    Level: intermediate
7660 
7661 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7662 @*/
7663 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7664 {
7665   PetscFunctionBegin;
7666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7667   *nblocks = mat->nblocks;
7668   *bsizes  = mat->bsizes;
7669   PetscFunctionReturn(0);
7670 }
7671 
7672 /*@
7673    MatSetBlockSizes - Sets the matrix block row and column sizes.
7674 
7675    Logically Collective on mat
7676 
7677    Input Parameters:
7678 +  mat - the matrix
7679 .  rbs - row block size
7680 -  cbs - column block size
7681 
7682    Notes:
7683     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7684     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7685     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7686 
7687     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7688     are compatible with the matrix local sizes.
7689 
7690     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7691 
7692    Level: intermediate
7693 
7694 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7695 @*/
7696 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7697 {
7698   PetscFunctionBegin;
7699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7700   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7701   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7702   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7703   if (mat->rmap->refcnt) {
7704     ISLocalToGlobalMapping l2g  = NULL;
7705     PetscLayout            nmap = NULL;
7706 
7707     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7708     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7709     PetscCall(PetscLayoutDestroy(&mat->rmap));
7710     mat->rmap          = nmap;
7711     mat->rmap->mapping = l2g;
7712   }
7713   if (mat->cmap->refcnt) {
7714     ISLocalToGlobalMapping l2g  = NULL;
7715     PetscLayout            nmap = NULL;
7716 
7717     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7718     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7719     PetscCall(PetscLayoutDestroy(&mat->cmap));
7720     mat->cmap          = nmap;
7721     mat->cmap->mapping = l2g;
7722   }
7723   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7724   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7725   PetscFunctionReturn(0);
7726 }
7727 
7728 /*@
7729    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7730 
7731    Logically Collective on mat
7732 
7733    Input Parameters:
7734 +  mat - the matrix
7735 .  fromRow - matrix from which to copy row block size
7736 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7737 
7738    Level: developer
7739 
7740 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7741 @*/
7742 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7743 {
7744   PetscFunctionBegin;
7745   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7746   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7747   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7748   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7749   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7750   PetscFunctionReturn(0);
7751 }
7752 
7753 /*@
7754    MatResidual - Default routine to calculate the residual r = b - Ax
7755 
7756    Collective on mat
7757 
7758    Input Parameters:
7759 +  mat - the matrix
7760 .  b   - the right-hand-side
7761 -  x   - the approximate solution
7762 
7763    Output Parameter:
7764 .  r - location to store the residual
7765 
7766    Level: developer
7767 
7768 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7769 @*/
7770 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7771 {
7772   PetscFunctionBegin;
7773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7774   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7775   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7776   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7777   PetscValidType(mat, 1);
7778   MatCheckPreallocated(mat, 1);
7779   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7780   if (!mat->ops->residual) {
7781     PetscCall(MatMult(mat, x, r));
7782     PetscCall(VecAYPX(r, -1.0, b));
7783   } else {
7784     PetscUseTypeMethod(mat, residual, b, x, r);
7785   }
7786   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7787   PetscFunctionReturn(0);
7788 }
7789 
7790 /*@C
7791     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7792 
7793    Collective on mat
7794 
7795     Input Parameters:
7796 +   mat - the matrix
7797 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7798 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7799 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7800                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7801                  always used.
7802 
7803     Output Parameters:
7804 +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7805 .   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
7806 .   ja - the column indices, use NULL if not needed
7807 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7808            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7809 
7810     Level: developer
7811 
7812     Notes:
7813     You CANNOT change any of the ia[] or ja[] values.
7814 
7815     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7816 
7817     Fortran Notes:
7818     In Fortran use
7819 $
7820 $      PetscInt ia(1), ja(1)
7821 $      PetscOffset iia, jja
7822 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7823 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7824 
7825      or
7826 $
7827 $    PetscInt, pointer :: ia(:),ja(:)
7828 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7829 $    ! Access the ith and jth entries via ia(i) and ja(j)
7830 
7831 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7832 @*/
7833 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7834 {
7835   PetscFunctionBegin;
7836   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7837   PetscValidType(mat, 1);
7838   if (n) PetscValidIntPointer(n, 5);
7839   if (ia) PetscValidPointer(ia, 6);
7840   if (ja) PetscValidPointer(ja, 7);
7841   if (done) PetscValidBoolPointer(done, 8);
7842   MatCheckPreallocated(mat, 1);
7843   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7844   else {
7845     if (done) *done = PETSC_TRUE;
7846     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7847     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7848     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7849   }
7850   PetscFunctionReturn(0);
7851 }
7852 
7853 /*@C
7854     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7855 
7856     Collective on mat
7857 
7858     Input Parameters:
7859 +   mat - the matrix
7860 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7861 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7862                 symmetrized
7863 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7864                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7865                  always used.
7866 .   n - number of columns in the (possibly compressed) matrix
7867 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7868 -   ja - the row indices
7869 
7870     Output Parameters:
7871 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7872 
7873     Level: developer
7874 
7875 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7876 @*/
7877 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7878 {
7879   PetscFunctionBegin;
7880   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7881   PetscValidType(mat, 1);
7882   PetscValidIntPointer(n, 5);
7883   if (ia) PetscValidPointer(ia, 6);
7884   if (ja) PetscValidPointer(ja, 7);
7885   PetscValidBoolPointer(done, 8);
7886   MatCheckPreallocated(mat, 1);
7887   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7888   else {
7889     *done = PETSC_TRUE;
7890     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7891   }
7892   PetscFunctionReturn(0);
7893 }
7894 
7895 /*@C
7896     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7897 
7898     Collective on mat
7899 
7900     Input Parameters:
7901 +   mat - the matrix
7902 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7903 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7904 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7905                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7906                  always used.
7907 .   n - size of (possibly compressed) matrix
7908 .   ia - the row pointers
7909 -   ja - the column indices
7910 
7911     Output Parameters:
7912 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7913 
7914     Note:
7915     This routine zeros out n, ia, and ja. This is to prevent accidental
7916     us of the array after it has been restored. If you pass NULL, it will
7917     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7918 
7919     Level: developer
7920 
7921 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7922 @*/
7923 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7924 {
7925   PetscFunctionBegin;
7926   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7927   PetscValidType(mat, 1);
7928   if (ia) PetscValidPointer(ia, 6);
7929   if (ja) PetscValidPointer(ja, 7);
7930   if (done) PetscValidBoolPointer(done, 8);
7931   MatCheckPreallocated(mat, 1);
7932 
7933   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7934   else {
7935     if (done) *done = PETSC_TRUE;
7936     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7937     if (n) *n = 0;
7938     if (ia) *ia = NULL;
7939     if (ja) *ja = NULL;
7940   }
7941   PetscFunctionReturn(0);
7942 }
7943 
7944 /*@C
7945     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7946 
7947     Collective on Mat
7948 
7949     Input Parameters:
7950 +   mat - the matrix
7951 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7952 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7953 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7954                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7955                  always used.
7956 
7957     Output Parameters:
7958 +   n - size of (possibly compressed) matrix
7959 .   ia - the column pointers
7960 .   ja - the row indices
7961 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7962 
7963     Level: developer
7964 
7965 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7966 @*/
7967 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7968 {
7969   PetscFunctionBegin;
7970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7971   PetscValidType(mat, 1);
7972   if (ia) PetscValidPointer(ia, 6);
7973   if (ja) PetscValidPointer(ja, 7);
7974   PetscValidBoolPointer(done, 8);
7975   MatCheckPreallocated(mat, 1);
7976 
7977   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7978   else {
7979     *done = PETSC_TRUE;
7980     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7981     if (n) *n = 0;
7982     if (ia) *ia = NULL;
7983     if (ja) *ja = NULL;
7984   }
7985   PetscFunctionReturn(0);
7986 }
7987 
7988 /*@C
7989     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7990 
7991     Collective on mat
7992 
7993     Input Parameters:
7994 +   mat - the matrix
7995 .   ncolors - max color value
7996 .   n   - number of entries in colorarray
7997 -   colorarray - array indicating color for each column
7998 
7999     Output Parameters:
8000 .   iscoloring - coloring generated using colorarray information
8001 
8002     Level: developer
8003 
8004 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8005 @*/
8006 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8007 {
8008   PetscFunctionBegin;
8009   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8010   PetscValidType(mat, 1);
8011   PetscValidIntPointer(colorarray, 4);
8012   PetscValidPointer(iscoloring, 5);
8013   MatCheckPreallocated(mat, 1);
8014 
8015   if (!mat->ops->coloringpatch) {
8016     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8017   } else {
8018     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8019   }
8020   PetscFunctionReturn(0);
8021 }
8022 
8023 /*@
8024    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8025 
8026    Logically Collective on mat
8027 
8028    Input Parameter:
8029 .  mat - the factored matrix to be reset
8030 
8031    Notes:
8032    This routine should be used only with factored matrices formed by in-place
8033    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8034    format).  This option can save memory, for example, when solving nonlinear
8035    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8036    ILU(0) preconditioner.
8037 
8038    Note that one can specify in-place ILU(0) factorization by calling
8039 .vb
8040      PCType(pc,PCILU);
8041      PCFactorSeUseInPlace(pc);
8042 .ve
8043    or by using the options -pc_type ilu -pc_factor_in_place
8044 
8045    In-place factorization ILU(0) can also be used as a local
8046    solver for the blocks within the block Jacobi or additive Schwarz
8047    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8048    for details on setting local solver options.
8049 
8050    Most users should employ the `KSP` interface for linear solvers
8051    instead of working directly with matrix algebra routines such as this.
8052    See, e.g., `KSPCreate()`.
8053 
8054    Level: developer
8055 
8056 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8057 @*/
8058 PetscErrorCode MatSetUnfactored(Mat mat)
8059 {
8060   PetscFunctionBegin;
8061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8062   PetscValidType(mat, 1);
8063   MatCheckPreallocated(mat, 1);
8064   mat->factortype = MAT_FACTOR_NONE;
8065   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8066   PetscUseTypeMethod(mat, setunfactored);
8067   PetscFunctionReturn(0);
8068 }
8069 
8070 /*MC
8071     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8072 
8073     Synopsis:
8074     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8075 
8076     Not collective
8077 
8078     Input Parameter:
8079 .   x - matrix
8080 
8081     Output Parameters:
8082 +   xx_v - the Fortran pointer to the array
8083 -   ierr - error code
8084 
8085     Example of Usage:
8086 .vb
8087       PetscScalar, pointer xx_v(:,:)
8088       ....
8089       call MatDenseGetArrayF90(x,xx_v,ierr)
8090       a = xx_v(3)
8091       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8092 .ve
8093 
8094     Level: advanced
8095 
8096 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8097 
8098 M*/
8099 
8100 /*MC
8101     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8102     accessed with `MatDenseGetArrayF90()`.
8103 
8104     Synopsis:
8105     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8106 
8107     Not collective
8108 
8109     Input Parameters:
8110 +   x - matrix
8111 -   xx_v - the Fortran90 pointer to the array
8112 
8113     Output Parameter:
8114 .   ierr - error code
8115 
8116     Example of Usage:
8117 .vb
8118        PetscScalar, pointer xx_v(:,:)
8119        ....
8120        call MatDenseGetArrayF90(x,xx_v,ierr)
8121        a = xx_v(3)
8122        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8123 .ve
8124 
8125     Level: advanced
8126 
8127 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8128 
8129 M*/
8130 
8131 /*MC
8132     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8133 
8134     Synopsis:
8135     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8136 
8137     Not collective
8138 
8139     Input Parameter:
8140 .   x - matrix
8141 
8142     Output Parameters:
8143 +   xx_v - the Fortran pointer to the array
8144 -   ierr - error code
8145 
8146     Example of Usage:
8147 .vb
8148       PetscScalar, pointer xx_v(:)
8149       ....
8150       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8151       a = xx_v(3)
8152       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8153 .ve
8154 
8155     Level: advanced
8156 
8157 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8158 
8159 M*/
8160 
8161 /*MC
8162     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8163     accessed with `MatSeqAIJGetArrayF90()`.
8164 
8165     Synopsis:
8166     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8167 
8168     Not collective
8169 
8170     Input Parameters:
8171 +   x - matrix
8172 -   xx_v - the Fortran90 pointer to the array
8173 
8174     Output Parameter:
8175 .   ierr - error code
8176 
8177     Example of Usage:
8178 .vb
8179        PetscScalar, pointer xx_v(:)
8180        ....
8181        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8182        a = xx_v(3)
8183        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8184 .ve
8185 
8186     Level: advanced
8187 
8188 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8189 
8190 M*/
8191 
8192 /*@
8193     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8194                       as the original matrix.
8195 
8196     Collective on mat
8197 
8198     Input Parameters:
8199 +   mat - the original matrix
8200 .   isrow - parallel IS containing the rows this processor should obtain
8201 .   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.
8202 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8203 
8204     Output Parameter:
8205 .   newmat - the new submatrix, of the same type as the old
8206 
8207     Level: advanced
8208 
8209     Notes:
8210     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8211 
8212     Some matrix types place restrictions on the row and column indices, such
8213     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;
8214     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8215 
8216     The index sets may not have duplicate entries.
8217 
8218       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8219    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8220    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8221    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8222    you are finished using it.
8223 
8224     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8225     the input matrix.
8226 
8227     If iscol is NULL then all columns are obtained (not supported in Fortran).
8228 
8229    Example usage:
8230    Consider the following 8x8 matrix with 34 non-zero values, that is
8231    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8232    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8233    as follows:
8234 
8235 .vb
8236             1  2  0  |  0  3  0  |  0  4
8237     Proc0   0  5  6  |  7  0  0  |  8  0
8238             9  0 10  | 11  0  0  | 12  0
8239     -------------------------------------
8240            13  0 14  | 15 16 17  |  0  0
8241     Proc1   0 18  0  | 19 20 21  |  0  0
8242             0  0  0  | 22 23  0  | 24  0
8243     -------------------------------------
8244     Proc2  25 26 27  |  0  0 28  | 29  0
8245            30  0  0  | 31 32 33  |  0 34
8246 .ve
8247 
8248     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8249 
8250 .vb
8251             2  0  |  0  3  0  |  0
8252     Proc0   5  6  |  7  0  0  |  8
8253     -------------------------------
8254     Proc1  18  0  | 19 20 21  |  0
8255     -------------------------------
8256     Proc2  26 27  |  0  0 28  | 29
8257             0  0  | 31 32 33  |  0
8258 .ve
8259 
8260 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8261 @*/
8262 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8263 {
8264   PetscMPIInt size;
8265   Mat        *local;
8266   IS          iscoltmp;
8267   PetscBool   flg;
8268 
8269   PetscFunctionBegin;
8270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8271   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8272   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8273   PetscValidPointer(newmat, 5);
8274   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8275   PetscValidType(mat, 1);
8276   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8277   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8278 
8279   MatCheckPreallocated(mat, 1);
8280   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8281 
8282   if (!iscol || isrow == iscol) {
8283     PetscBool   stride;
8284     PetscMPIInt grabentirematrix = 0, grab;
8285     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8286     if (stride) {
8287       PetscInt first, step, n, rstart, rend;
8288       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8289       if (step == 1) {
8290         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8291         if (rstart == first) {
8292           PetscCall(ISGetLocalSize(isrow, &n));
8293           if (n == rend - rstart) grabentirematrix = 1;
8294         }
8295       }
8296     }
8297     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8298     if (grab) {
8299       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8300       if (cll == MAT_INITIAL_MATRIX) {
8301         *newmat = mat;
8302         PetscCall(PetscObjectReference((PetscObject)mat));
8303       }
8304       PetscFunctionReturn(0);
8305     }
8306   }
8307 
8308   if (!iscol) {
8309     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8310   } else {
8311     iscoltmp = iscol;
8312   }
8313 
8314   /* if original matrix is on just one processor then use submatrix generated */
8315   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8316     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8317     goto setproperties;
8318   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8319     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8320     *newmat = *local;
8321     PetscCall(PetscFree(local));
8322     goto setproperties;
8323   } else if (!mat->ops->createsubmatrix) {
8324     /* Create a new matrix type that implements the operation using the full matrix */
8325     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8326     switch (cll) {
8327     case MAT_INITIAL_MATRIX:
8328       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8329       break;
8330     case MAT_REUSE_MATRIX:
8331       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8332       break;
8333     default:
8334       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8335     }
8336     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8337     goto setproperties;
8338   }
8339 
8340   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8341   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8342   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8343 
8344 setproperties:
8345   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8346   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8347   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8348   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8349   PetscFunctionReturn(0);
8350 }
8351 
8352 /*@
8353    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8354 
8355    Not Collective
8356 
8357    Input Parameters:
8358 +  A - the matrix we wish to propagate options from
8359 -  B - the matrix we wish to propagate options to
8360 
8361    Level: beginner
8362 
8363    Note:
8364    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8365 
8366 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8367 @*/
8368 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8369 {
8370   PetscFunctionBegin;
8371   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8372   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8373   B->symmetry_eternal            = A->symmetry_eternal;
8374   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8375   B->symmetric                   = A->symmetric;
8376   B->structurally_symmetric      = A->structurally_symmetric;
8377   B->spd                         = A->spd;
8378   B->hermitian                   = A->hermitian;
8379   PetscFunctionReturn(0);
8380 }
8381 
8382 /*@
8383    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8384    used during the assembly process to store values that belong to
8385    other processors.
8386 
8387    Not Collective
8388 
8389    Input Parameters:
8390 +  mat   - the matrix
8391 .  size  - the initial size of the stash.
8392 -  bsize - the initial size of the block-stash(if used).
8393 
8394    Options Database Keys:
8395 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8396 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8397 
8398    Level: intermediate
8399 
8400    Notes:
8401      The block-stash is used for values set with `MatSetValuesBlocked()` while
8402      the stash is used for values set with `MatSetValues()`
8403 
8404      Run with the option -info and look for output of the form
8405      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8406      to determine the appropriate value, MM, to use for size and
8407      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8408      to determine the value, BMM to use for bsize
8409 
8410 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8411 @*/
8412 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8413 {
8414   PetscFunctionBegin;
8415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8416   PetscValidType(mat, 1);
8417   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8418   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8419   PetscFunctionReturn(0);
8420 }
8421 
8422 /*@
8423    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8424      the matrix
8425 
8426    Neighbor-wise Collective on mat
8427 
8428    Input Parameters:
8429 +  mat   - the matrix
8430 .  x,y - the vectors
8431 -  w - where the result is stored
8432 
8433    Level: intermediate
8434 
8435    Notes:
8436     w may be the same vector as y.
8437 
8438     This allows one to use either the restriction or interpolation (its transpose)
8439     matrix to do the interpolation
8440 
8441 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8442 @*/
8443 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8444 {
8445   PetscInt M, N, Ny;
8446 
8447   PetscFunctionBegin;
8448   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8449   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8450   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8451   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8452   PetscCall(MatGetSize(A, &M, &N));
8453   PetscCall(VecGetSize(y, &Ny));
8454   if (M == Ny) {
8455     PetscCall(MatMultAdd(A, x, y, w));
8456   } else {
8457     PetscCall(MatMultTransposeAdd(A, x, y, w));
8458   }
8459   PetscFunctionReturn(0);
8460 }
8461 
8462 /*@
8463    MatInterpolate - y = A*x or A'*x depending on the shape of
8464      the matrix
8465 
8466    Neighbor-wise Collective on mat
8467 
8468    Input Parameters:
8469 +  mat   - the matrix
8470 -  x,y - the vectors
8471 
8472    Level: intermediate
8473 
8474    Note:
8475     This allows one to use either the restriction or interpolation (its transpose)
8476     matrix to do the interpolation
8477 
8478 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8479 @*/
8480 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8481 {
8482   PetscInt M, N, Ny;
8483 
8484   PetscFunctionBegin;
8485   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8486   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8487   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8488   PetscCall(MatGetSize(A, &M, &N));
8489   PetscCall(VecGetSize(y, &Ny));
8490   if (M == Ny) {
8491     PetscCall(MatMult(A, x, y));
8492   } else {
8493     PetscCall(MatMultTranspose(A, x, y));
8494   }
8495   PetscFunctionReturn(0);
8496 }
8497 
8498 /*@
8499    MatRestrict - y = A*x or A'*x
8500 
8501    Neighbor-wise Collective on Mat
8502 
8503    Input Parameters:
8504 +  mat   - the matrix
8505 -  x,y - the vectors
8506 
8507    Level: intermediate
8508 
8509    Note:
8510     This allows one to use either the restriction or interpolation (its transpose)
8511     matrix to do the restriction
8512 
8513 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8514 @*/
8515 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8516 {
8517   PetscInt M, N, Ny;
8518 
8519   PetscFunctionBegin;
8520   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8521   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8522   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8523   PetscCall(MatGetSize(A, &M, &N));
8524   PetscCall(VecGetSize(y, &Ny));
8525   if (M == Ny) {
8526     PetscCall(MatMult(A, x, y));
8527   } else {
8528     PetscCall(MatMultTranspose(A, x, y));
8529   }
8530   PetscFunctionReturn(0);
8531 }
8532 
8533 /*@
8534    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8535 
8536    Neighbor-wise Collective on Mat
8537 
8538    Input Parameters:
8539 +  mat   - the matrix
8540 -  w, x - the input dense matrices
8541 
8542    Output Parameters:
8543 .  y - the output dense matrix
8544 
8545    Level: intermediate
8546 
8547    Note:
8548     This allows one to use either the restriction or interpolation (its transpose)
8549     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8550     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8551 
8552 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8553 @*/
8554 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8555 {
8556   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8557   PetscBool trans = PETSC_TRUE;
8558   MatReuse  reuse = MAT_INITIAL_MATRIX;
8559 
8560   PetscFunctionBegin;
8561   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8562   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8563   PetscValidType(x, 2);
8564   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8565   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8566   PetscCall(MatGetSize(A, &M, &N));
8567   PetscCall(MatGetSize(x, &Mx, &Nx));
8568   if (N == Mx) trans = PETSC_FALSE;
8569   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);
8570   Mo = trans ? N : M;
8571   if (*y) {
8572     PetscCall(MatGetSize(*y, &My, &Ny));
8573     if (Mo == My && Nx == Ny) {
8574       reuse = MAT_REUSE_MATRIX;
8575     } else {
8576       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);
8577       PetscCall(MatDestroy(y));
8578     }
8579   }
8580 
8581   if (w && *y == w) { /* this is to minimize changes in PCMG */
8582     PetscBool flg;
8583 
8584     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8585     if (w) {
8586       PetscInt My, Ny, Mw, Nw;
8587 
8588       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8589       PetscCall(MatGetSize(*y, &My, &Ny));
8590       PetscCall(MatGetSize(w, &Mw, &Nw));
8591       if (!flg || My != Mw || Ny != Nw) w = NULL;
8592     }
8593     if (!w) {
8594       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8595       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8596       PetscCall(PetscObjectDereference((PetscObject)w));
8597     } else {
8598       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8599     }
8600   }
8601   if (!trans) {
8602     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8603   } else {
8604     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8605   }
8606   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8607   PetscFunctionReturn(0);
8608 }
8609 
8610 /*@
8611    MatMatInterpolate - Y = A*X or A'*X
8612 
8613    Neighbor-wise Collective on Mat
8614 
8615    Input Parameters:
8616 +  mat   - the matrix
8617 -  x - the input dense matrix
8618 
8619    Output Parameters:
8620 .  y - the output dense matrix
8621 
8622    Level: intermediate
8623 
8624    Note:
8625     This allows one to use either the restriction or interpolation (its transpose)
8626     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8627     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8628 
8629 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8630 @*/
8631 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8632 {
8633   PetscFunctionBegin;
8634   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8635   PetscFunctionReturn(0);
8636 }
8637 
8638 /*@
8639    MatMatRestrict - Y = A*X or A'*X
8640 
8641    Neighbor-wise Collective on Mat
8642 
8643    Input Parameters:
8644 +  mat   - the matrix
8645 -  x - the input dense matrix
8646 
8647    Output Parameters:
8648 .  y - the output dense matrix
8649 
8650    Level: intermediate
8651 
8652    Note:
8653     This allows one to use either the restriction or interpolation (its transpose)
8654     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8655     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8656 
8657 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8658 @*/
8659 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8660 {
8661   PetscFunctionBegin;
8662   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8663   PetscFunctionReturn(0);
8664 }
8665 
8666 /*@
8667    MatGetNullSpace - retrieves the null space of a matrix.
8668 
8669    Logically Collective on mat
8670 
8671    Input Parameters:
8672 +  mat - the matrix
8673 -  nullsp - the null space object
8674 
8675    Level: developer
8676 
8677 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8678 @*/
8679 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8680 {
8681   PetscFunctionBegin;
8682   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8683   PetscValidPointer(nullsp, 2);
8684   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8685   PetscFunctionReturn(0);
8686 }
8687 
8688 /*@
8689    MatSetNullSpace - attaches a null space to a matrix.
8690 
8691    Logically Collective on mat
8692 
8693    Input Parameters:
8694 +  mat - the matrix
8695 -  nullsp - the null space object
8696 
8697    Level: advanced
8698 
8699    Notes:
8700       This null space is used by the `KSP` linear solvers to solve singular systems.
8701 
8702       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
8703 
8704       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
8705       to zero but the linear system will still be solved in a least squares sense.
8706 
8707       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8708    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).
8709    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
8710    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
8711    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).
8712    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8713 
8714     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8715     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8716     routine also automatically calls `MatSetTransposeNullSpace()`.
8717 
8718     The user should call `MatNullSpaceDestroy()`.
8719 
8720 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8721           `KSPSetPCSide()`
8722 @*/
8723 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8724 {
8725   PetscFunctionBegin;
8726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8727   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8728   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8729   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8730   mat->nullsp = nullsp;
8731   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8732   PetscFunctionReturn(0);
8733 }
8734 
8735 /*@
8736    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8737 
8738    Logically Collective on mat
8739 
8740    Input Parameters:
8741 +  mat - the matrix
8742 -  nullsp - the null space object
8743 
8744    Level: developer
8745 
8746 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8747 @*/
8748 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8749 {
8750   PetscFunctionBegin;
8751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8752   PetscValidType(mat, 1);
8753   PetscValidPointer(nullsp, 2);
8754   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8755   PetscFunctionReturn(0);
8756 }
8757 
8758 /*@
8759    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8760 
8761    Logically Collective on mat
8762 
8763    Input Parameters:
8764 +  mat - the matrix
8765 -  nullsp - the null space object
8766 
8767    Level: advanced
8768 
8769    Notes:
8770    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8771 
8772    See `MatSetNullSpace()`
8773 
8774 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8775 @*/
8776 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8777 {
8778   PetscFunctionBegin;
8779   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8780   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8781   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8782   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8783   mat->transnullsp = nullsp;
8784   PetscFunctionReturn(0);
8785 }
8786 
8787 /*@
8788    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8789         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8790 
8791    Logically Collective on mat
8792 
8793    Input Parameters:
8794 +  mat - the matrix
8795 -  nullsp - the null space object
8796 
8797    Level: advanced
8798 
8799    Notes:
8800    Overwrites any previous near null space that may have been attached
8801 
8802    You can remove the null space by calling this routine with an nullsp of NULL
8803 
8804 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8805 @*/
8806 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8807 {
8808   PetscFunctionBegin;
8809   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8810   PetscValidType(mat, 1);
8811   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8812   MatCheckPreallocated(mat, 1);
8813   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8814   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8815   mat->nearnullsp = nullsp;
8816   PetscFunctionReturn(0);
8817 }
8818 
8819 /*@
8820    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8821 
8822    Not Collective
8823 
8824    Input Parameter:
8825 .  mat - the matrix
8826 
8827    Output Parameter:
8828 .  nullsp - the null space object, NULL if not set
8829 
8830    Level: advanced
8831 
8832 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8833 @*/
8834 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8835 {
8836   PetscFunctionBegin;
8837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8838   PetscValidType(mat, 1);
8839   PetscValidPointer(nullsp, 2);
8840   MatCheckPreallocated(mat, 1);
8841   *nullsp = mat->nearnullsp;
8842   PetscFunctionReturn(0);
8843 }
8844 
8845 /*@C
8846    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8847 
8848    Collective on mat
8849 
8850    Input Parameters:
8851 +  mat - the matrix
8852 .  row - row/column permutation
8853 .  fill - expected fill factor >= 1.0
8854 -  level - level of fill, for ICC(k)
8855 
8856    Notes:
8857    Probably really in-place only when level of fill is zero, otherwise allocates
8858    new space to store factored matrix and deletes previous memory.
8859 
8860    Most users should employ the `KSP` interface for linear solvers
8861    instead of working directly with matrix algebra routines such as this.
8862    See, e.g., `KSPCreate()`.
8863 
8864    Level: developer
8865 
8866    Developer Note:
8867    The Fortran interface is not autogenerated as the f90
8868    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8869 
8870 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8871 @*/
8872 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8873 {
8874   PetscFunctionBegin;
8875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8876   PetscValidType(mat, 1);
8877   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8878   PetscValidPointer(info, 3);
8879   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8880   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8881   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8882   MatCheckPreallocated(mat, 1);
8883   PetscUseTypeMethod(mat, iccfactor, row, info);
8884   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8885   PetscFunctionReturn(0);
8886 }
8887 
8888 /*@
8889    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8890          ghosted ones.
8891 
8892    Not Collective
8893 
8894    Input Parameters:
8895 +  mat - the matrix
8896 -  diag - the diagonal values, including ghost ones
8897 
8898    Level: developer
8899 
8900    Notes:
8901     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8902 
8903     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8904 
8905 .seealso: `MatDiagonalScale()`
8906 @*/
8907 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8908 {
8909   PetscMPIInt size;
8910 
8911   PetscFunctionBegin;
8912   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8913   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8914   PetscValidType(mat, 1);
8915 
8916   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8917   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8918   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8919   if (size == 1) {
8920     PetscInt n, m;
8921     PetscCall(VecGetSize(diag, &n));
8922     PetscCall(MatGetSize(mat, NULL, &m));
8923     if (m == n) {
8924       PetscCall(MatDiagonalScale(mat, NULL, diag));
8925     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8926   } else {
8927     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8928   }
8929   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8930   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8931   PetscFunctionReturn(0);
8932 }
8933 
8934 /*@
8935    MatGetInertia - Gets the inertia from a factored matrix
8936 
8937    Collective on mat
8938 
8939    Input Parameter:
8940 .  mat - the matrix
8941 
8942    Output Parameters:
8943 +   nneg - number of negative eigenvalues
8944 .   nzero - number of zero eigenvalues
8945 -   npos - number of positive eigenvalues
8946 
8947    Level: advanced
8948 
8949    Note:
8950     Matrix must have been factored by `MatCholeskyFactor()`
8951 
8952 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8953 @*/
8954 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8955 {
8956   PetscFunctionBegin;
8957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8958   PetscValidType(mat, 1);
8959   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8960   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8961   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8962   PetscFunctionReturn(0);
8963 }
8964 
8965 /* ----------------------------------------------------------------*/
8966 /*@C
8967    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8968 
8969    Neighbor-wise Collective on mat
8970 
8971    Input Parameters:
8972 +  mat - the factored matrix obtained with `MatGetFactor()`
8973 -  b - the right-hand-side vectors
8974 
8975    Output Parameter:
8976 .  x - the result vectors
8977 
8978    Note:
8979    The vectors b and x cannot be the same.  I.e., one cannot
8980    call `MatSolves`(A,x,x).
8981 
8982    Level: developer
8983 
8984 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8985 @*/
8986 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8987 {
8988   PetscFunctionBegin;
8989   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8990   PetscValidType(mat, 1);
8991   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
8992   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8993   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8994 
8995   MatCheckPreallocated(mat, 1);
8996   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
8997   PetscUseTypeMethod(mat, solves, b, x);
8998   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
8999   PetscFunctionReturn(0);
9000 }
9001 
9002 /*@
9003    MatIsSymmetric - Test whether a matrix is symmetric
9004 
9005    Collective on mat
9006 
9007    Input Parameters:
9008 +  A - the matrix to test
9009 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9010 
9011    Output Parameters:
9012 .  flg - the result
9013 
9014    Notes:
9015     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9016 
9017     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9018 
9019     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9020     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9021 
9022    Level: intermediate
9023 
9024 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9025           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9026 @*/
9027 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9028 {
9029   PetscFunctionBegin;
9030   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9031   PetscValidBoolPointer(flg, 3);
9032 
9033   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9034   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9035   else {
9036     if (!A->ops->issymmetric) {
9037       MatType mattype;
9038       PetscCall(MatGetType(A, &mattype));
9039       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9040     }
9041     PetscUseTypeMethod(A, issymmetric, tol, flg);
9042     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9043   }
9044   PetscFunctionReturn(0);
9045 }
9046 
9047 /*@
9048    MatIsHermitian - Test whether a matrix is Hermitian
9049 
9050    Collective on Mat
9051 
9052    Input Parameters:
9053 +  A - the matrix to test
9054 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9055 
9056    Output Parameters:
9057 .  flg - the result
9058 
9059    Level: intermediate
9060 
9061    Notes:
9062     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9063 
9064     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9065 
9066     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9067     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9068 
9069 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9070           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9071 @*/
9072 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9073 {
9074   PetscFunctionBegin;
9075   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9076   PetscValidBoolPointer(flg, 3);
9077 
9078   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9079   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9080   else {
9081     if (!A->ops->ishermitian) {
9082       MatType mattype;
9083       PetscCall(MatGetType(A, &mattype));
9084       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9085     }
9086     PetscUseTypeMethod(A, ishermitian, tol, flg);
9087     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9088   }
9089   PetscFunctionReturn(0);
9090 }
9091 
9092 /*@
9093    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9094 
9095    Not Collective
9096 
9097    Input Parameter:
9098 .  A - the matrix to check
9099 
9100    Output Parameters:
9101 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9102 -  flg - the result (only valid if set is `PETSC_TRUE`)
9103 
9104    Level: advanced
9105 
9106    Notes:
9107    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9108    if you want it explicitly checked
9109 
9110     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9111     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9112 
9113 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9114 @*/
9115 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9116 {
9117   PetscFunctionBegin;
9118   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9119   PetscValidBoolPointer(set, 2);
9120   PetscValidBoolPointer(flg, 3);
9121   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9122     *set = PETSC_TRUE;
9123     *flg = PetscBool3ToBool(A->symmetric);
9124   } else {
9125     *set = PETSC_FALSE;
9126   }
9127   PetscFunctionReturn(0);
9128 }
9129 
9130 /*@
9131    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9132 
9133    Not Collective
9134 
9135    Input Parameter:
9136 .  A - the matrix to check
9137 
9138    Output Parameters:
9139 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9140 -  flg - the result (only valid if set is `PETSC_TRUE`)
9141 
9142    Level: advanced
9143 
9144    Notes:
9145    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9146 
9147    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9148    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9149 
9150 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9151 @*/
9152 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9153 {
9154   PetscFunctionBegin;
9155   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9156   PetscValidBoolPointer(set, 2);
9157   PetscValidBoolPointer(flg, 3);
9158   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9159     *set = PETSC_TRUE;
9160     *flg = PetscBool3ToBool(A->spd);
9161   } else {
9162     *set = PETSC_FALSE;
9163   }
9164   PetscFunctionReturn(0);
9165 }
9166 
9167 /*@
9168    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9169 
9170    Not Collective
9171 
9172    Input Parameter:
9173 .  A - the matrix to check
9174 
9175    Output Parameters:
9176 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9177 -  flg - the result (only valid if set is `PETSC_TRUE`)
9178 
9179    Level: advanced
9180 
9181    Notes:
9182    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9183    if you want it explicitly checked
9184 
9185    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9186    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9187 
9188 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9189 @*/
9190 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9191 {
9192   PetscFunctionBegin;
9193   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9194   PetscValidBoolPointer(set, 2);
9195   PetscValidBoolPointer(flg, 3);
9196   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9197     *set = PETSC_TRUE;
9198     *flg = PetscBool3ToBool(A->hermitian);
9199   } else {
9200     *set = PETSC_FALSE;
9201   }
9202   PetscFunctionReturn(0);
9203 }
9204 
9205 /*@
9206    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9207 
9208    Collective on Mat
9209 
9210    Input Parameter:
9211 .  A - the matrix to test
9212 
9213    Output Parameters:
9214 .  flg - the result
9215 
9216    Notes:
9217    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9218 
9219    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
9220    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9221 
9222    Level: intermediate
9223 
9224 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9225 @*/
9226 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9227 {
9228   PetscFunctionBegin;
9229   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9230   PetscValidBoolPointer(flg, 2);
9231   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9232     *flg = PetscBool3ToBool(A->structurally_symmetric);
9233   } else {
9234     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9235     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9236   }
9237   PetscFunctionReturn(0);
9238 }
9239 
9240 /*@
9241    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9242 
9243    Not Collective
9244 
9245    Input Parameter:
9246 .  A - the matrix to check
9247 
9248    Output Parameters:
9249 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9250 -  flg - the result (only valid if set is PETSC_TRUE)
9251 
9252    Level: advanced
9253 
9254    Notes:
9255    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
9256    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9257 
9258    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9259 
9260 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9261 @*/
9262 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9263 {
9264   PetscFunctionBegin;
9265   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9266   PetscValidBoolPointer(set, 2);
9267   PetscValidBoolPointer(flg, 3);
9268   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9269     *set = PETSC_TRUE;
9270     *flg = PetscBool3ToBool(A->structurally_symmetric);
9271   } else {
9272     *set = PETSC_FALSE;
9273   }
9274   PetscFunctionReturn(0);
9275 }
9276 
9277 /*@
9278    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9279        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9280 
9281     Not collective
9282 
9283    Input Parameter:
9284 .   mat - the matrix
9285 
9286    Output Parameters:
9287 +   nstash   - the size of the stash
9288 .   reallocs - the number of additional mallocs incurred.
9289 .   bnstash   - the size of the block stash
9290 -   breallocs - the number of additional mallocs incurred.in the block stash
9291 
9292    Level: advanced
9293 
9294 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9295 @*/
9296 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9297 {
9298   PetscFunctionBegin;
9299   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9300   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9301   PetscFunctionReturn(0);
9302 }
9303 
9304 /*@C
9305    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9306    parallel layout, `PetscLayout` for rows and columns
9307 
9308    Collective on mat
9309 
9310    Input Parameter:
9311 .  mat - the matrix
9312 
9313    Output Parameters:
9314 +   right - (optional) vector that the matrix can be multiplied against
9315 -   left - (optional) vector that the matrix vector product can be stored in
9316 
9317    Notes:
9318     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()`.
9319 
9320     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9321 
9322   Level: advanced
9323 
9324 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9325 @*/
9326 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9327 {
9328   PetscFunctionBegin;
9329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9330   PetscValidType(mat, 1);
9331   if (mat->ops->getvecs) {
9332     PetscUseTypeMethod(mat, getvecs, right, left);
9333   } else {
9334     PetscInt rbs, cbs;
9335     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9336     if (right) {
9337       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9338       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9339       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9340       PetscCall(VecSetBlockSize(*right, cbs));
9341       PetscCall(VecSetType(*right, mat->defaultvectype));
9342 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9343       if (mat->boundtocpu && mat->bindingpropagates) {
9344         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9345         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9346       }
9347 #endif
9348       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9349     }
9350     if (left) {
9351       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9352       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9353       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9354       PetscCall(VecSetBlockSize(*left, rbs));
9355       PetscCall(VecSetType(*left, mat->defaultvectype));
9356 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9357       if (mat->boundtocpu && mat->bindingpropagates) {
9358         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9359         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9360       }
9361 #endif
9362       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9363     }
9364   }
9365   PetscFunctionReturn(0);
9366 }
9367 
9368 /*@C
9369    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9370      with default values.
9371 
9372    Not Collective
9373 
9374    Input Parameters:
9375 .    info - the `MatFactorInfo` data structure
9376 
9377    Notes:
9378     The solvers are generally used through the `KSP` and `PC` objects, for example
9379           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9380 
9381     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9382 
9383    Level: developer
9384 
9385    Developer Note:
9386    The Fortran interface is not autogenerated as the f90
9387    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9388 
9389 .seealso: `MatGetFactor()`, `MatFactorInfo`
9390 @*/
9391 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9392 {
9393   PetscFunctionBegin;
9394   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9395   PetscFunctionReturn(0);
9396 }
9397 
9398 /*@
9399    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9400 
9401    Collective on mat
9402 
9403    Input Parameters:
9404 +  mat - the factored matrix
9405 -  is - the index set defining the Schur indices (0-based)
9406 
9407    Notes:
9408     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9409 
9410    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9411 
9412    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9413 
9414    Level: advanced
9415 
9416 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9417           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9418 
9419 @*/
9420 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9421 {
9422   PetscErrorCode (*f)(Mat, IS);
9423 
9424   PetscFunctionBegin;
9425   PetscValidType(mat, 1);
9426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9427   PetscValidType(is, 2);
9428   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9429   PetscCheckSameComm(mat, 1, is, 2);
9430   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9431   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9432   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9433   PetscCall(MatDestroy(&mat->schur));
9434   PetscCall((*f)(mat, is));
9435   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9436   PetscFunctionReturn(0);
9437 }
9438 
9439 /*@
9440   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9441 
9442    Logically Collective on mat
9443 
9444    Input Parameters:
9445 +  F - the factored matrix obtained by calling `MatGetFactor()`
9446 .  S - location where to return the Schur complement, can be NULL
9447 -  status - the status of the Schur complement matrix, can be NULL
9448 
9449    Notes:
9450    You must call `MatFactorSetSchurIS()` before calling this routine.
9451 
9452    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9453 
9454    The routine provides a copy of the Schur matrix stored within the solver data structures.
9455    The caller must destroy the object when it is no longer needed.
9456    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9457 
9458    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)
9459 
9460    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9461 
9462    Developer Note:
9463     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9464    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9465 
9466    Level: advanced
9467 
9468 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9469 @*/
9470 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9471 {
9472   PetscFunctionBegin;
9473   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9474   if (S) PetscValidPointer(S, 2);
9475   if (status) PetscValidPointer(status, 3);
9476   if (S) {
9477     PetscErrorCode (*f)(Mat, Mat *);
9478 
9479     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9480     if (f) {
9481       PetscCall((*f)(F, S));
9482     } else {
9483       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9484     }
9485   }
9486   if (status) *status = F->schur_status;
9487   PetscFunctionReturn(0);
9488 }
9489 
9490 /*@
9491   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9492 
9493    Logically Collective on mat
9494 
9495    Input Parameters:
9496 +  F - the factored matrix obtained by calling `MatGetFactor()`
9497 .  *S - location where to return the Schur complement, can be NULL
9498 -  status - the status of the Schur complement matrix, can be NULL
9499 
9500    Notes:
9501    You must call `MatFactorSetSchurIS()` before calling this routine.
9502 
9503    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9504 
9505    The routine returns a the Schur Complement stored within the data strutures of the solver.
9506 
9507    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9508 
9509    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9510 
9511    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9512 
9513    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9514 
9515    Level: advanced
9516 
9517 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9518 @*/
9519 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9520 {
9521   PetscFunctionBegin;
9522   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9523   if (S) PetscValidPointer(S, 2);
9524   if (status) PetscValidPointer(status, 3);
9525   if (S) *S = F->schur;
9526   if (status) *status = F->schur_status;
9527   PetscFunctionReturn(0);
9528 }
9529 
9530 /*@
9531   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9532 
9533    Logically Collective on mat
9534 
9535    Input Parameters:
9536 +  F - the factored matrix obtained by calling `MatGetFactor()`
9537 .  *S - location where the Schur complement is stored
9538 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9539 
9540    Level: advanced
9541 
9542 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9543 @*/
9544 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9545 {
9546   PetscFunctionBegin;
9547   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9548   if (S) {
9549     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9550     *S = NULL;
9551   }
9552   F->schur_status = status;
9553   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9554   PetscFunctionReturn(0);
9555 }
9556 
9557 /*@
9558   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9559 
9560    Logically Collective on mat
9561 
9562    Input Parameters:
9563 +  F - the factored matrix obtained by calling `MatGetFactor()`
9564 .  rhs - location where the right hand side of the Schur complement system is stored
9565 -  sol - location where the solution of the Schur complement system has to be returned
9566 
9567    Notes:
9568    The sizes of the vectors should match the size of the Schur complement
9569 
9570    Must be called after `MatFactorSetSchurIS()`
9571 
9572    Level: advanced
9573 
9574 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9575 @*/
9576 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9577 {
9578   PetscFunctionBegin;
9579   PetscValidType(F, 1);
9580   PetscValidType(rhs, 2);
9581   PetscValidType(sol, 3);
9582   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9583   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9584   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9585   PetscCheckSameComm(F, 1, rhs, 2);
9586   PetscCheckSameComm(F, 1, sol, 3);
9587   PetscCall(MatFactorFactorizeSchurComplement(F));
9588   switch (F->schur_status) {
9589   case MAT_FACTOR_SCHUR_FACTORED:
9590     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9591     break;
9592   case MAT_FACTOR_SCHUR_INVERTED:
9593     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9594     break;
9595   default:
9596     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9597   }
9598   PetscFunctionReturn(0);
9599 }
9600 
9601 /*@
9602   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9603 
9604    Logically Collective on mat
9605 
9606    Input Parameters:
9607 +  F - the factored matrix obtained by calling `MatGetFactor()`
9608 .  rhs - location where the right hand side of the Schur complement system is stored
9609 -  sol - location where the solution of the Schur complement system has to be returned
9610 
9611    Notes:
9612    The sizes of the vectors should match the size of the Schur complement
9613 
9614    Must be called after `MatFactorSetSchurIS()`
9615 
9616    Level: advanced
9617 
9618 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9619 @*/
9620 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9621 {
9622   PetscFunctionBegin;
9623   PetscValidType(F, 1);
9624   PetscValidType(rhs, 2);
9625   PetscValidType(sol, 3);
9626   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9627   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9628   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9629   PetscCheckSameComm(F, 1, rhs, 2);
9630   PetscCheckSameComm(F, 1, sol, 3);
9631   PetscCall(MatFactorFactorizeSchurComplement(F));
9632   switch (F->schur_status) {
9633   case MAT_FACTOR_SCHUR_FACTORED:
9634     PetscCall(MatSolve(F->schur, rhs, sol));
9635     break;
9636   case MAT_FACTOR_SCHUR_INVERTED:
9637     PetscCall(MatMult(F->schur, rhs, sol));
9638     break;
9639   default:
9640     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9641   }
9642   PetscFunctionReturn(0);
9643 }
9644 
9645 /*@
9646   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9647 
9648    Logically Collective on F
9649 
9650    Input Parameters:
9651 .  F - the factored matrix obtained by calling `MatGetFactor()`
9652 
9653    Notes:
9654     Must be called after `MatFactorSetSchurIS()`.
9655 
9656    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9657 
9658    Level: advanced
9659 
9660 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9661 @*/
9662 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9663 {
9664   PetscFunctionBegin;
9665   PetscValidType(F, 1);
9666   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9667   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9668   PetscCall(MatFactorFactorizeSchurComplement(F));
9669   PetscCall(MatFactorInvertSchurComplement_Private(F));
9670   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9671   PetscFunctionReturn(0);
9672 }
9673 
9674 /*@
9675   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9676 
9677    Logically Collective on mat
9678 
9679    Input Parameters:
9680 .  F - the factored matrix obtained by calling `MatGetFactor()`
9681 
9682    Note:
9683     Must be called after `MatFactorSetSchurIS()`
9684 
9685    Level: advanced
9686 
9687 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9688 @*/
9689 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9690 {
9691   PetscFunctionBegin;
9692   PetscValidType(F, 1);
9693   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9694   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9695   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9696   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9697   PetscFunctionReturn(0);
9698 }
9699 
9700 /*@
9701    MatPtAP - Creates the matrix product C = P^T * A * P
9702 
9703    Neighbor-wise Collective on A
9704 
9705    Input Parameters:
9706 +  A - the matrix
9707 .  P - the projection matrix
9708 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9709 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9710           if the result is a dense matrix this is irrelevant
9711 
9712    Output Parameters:
9713 .  C - the product matrix
9714 
9715    Notes:
9716    C will be created and must be destroyed by the user with `MatDestroy()`.
9717 
9718    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9719 
9720    Developer Note:
9721    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9722 
9723    Level: intermediate
9724 
9725 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9726 @*/
9727 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9728 {
9729   PetscFunctionBegin;
9730   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9731   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9732 
9733   if (scall == MAT_INITIAL_MATRIX) {
9734     PetscCall(MatProductCreate(A, P, NULL, C));
9735     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9736     PetscCall(MatProductSetAlgorithm(*C, "default"));
9737     PetscCall(MatProductSetFill(*C, fill));
9738 
9739     (*C)->product->api_user = PETSC_TRUE;
9740     PetscCall(MatProductSetFromOptions(*C));
9741     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);
9742     PetscCall(MatProductSymbolic(*C));
9743   } else { /* scall == MAT_REUSE_MATRIX */
9744     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9745   }
9746 
9747   PetscCall(MatProductNumeric(*C));
9748   (*C)->symmetric = A->symmetric;
9749   (*C)->spd       = A->spd;
9750   PetscFunctionReturn(0);
9751 }
9752 
9753 /*@
9754    MatRARt - Creates the matrix product C = R * A * R^T
9755 
9756    Neighbor-wise Collective on A
9757 
9758    Input Parameters:
9759 +  A - the matrix
9760 .  R - the projection matrix
9761 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9762 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9763           if the result is a dense matrix this is irrelevant
9764 
9765    Output Parameters:
9766 .  C - the product matrix
9767 
9768    Notes:
9769    C will be created and must be destroyed by the user with `MatDestroy()`.
9770 
9771    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9772 
9773    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9774    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9775    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9776    We recommend using MatPtAP().
9777 
9778    Level: intermediate
9779 
9780 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9781 @*/
9782 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9783 {
9784   PetscFunctionBegin;
9785   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9786   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9787 
9788   if (scall == MAT_INITIAL_MATRIX) {
9789     PetscCall(MatProductCreate(A, R, NULL, C));
9790     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9791     PetscCall(MatProductSetAlgorithm(*C, "default"));
9792     PetscCall(MatProductSetFill(*C, fill));
9793 
9794     (*C)->product->api_user = PETSC_TRUE;
9795     PetscCall(MatProductSetFromOptions(*C));
9796     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);
9797     PetscCall(MatProductSymbolic(*C));
9798   } else { /* scall == MAT_REUSE_MATRIX */
9799     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9800   }
9801 
9802   PetscCall(MatProductNumeric(*C));
9803   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9804   PetscFunctionReturn(0);
9805 }
9806 
9807 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9808 {
9809   PetscFunctionBegin;
9810   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9811 
9812   if (scall == MAT_INITIAL_MATRIX) {
9813     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9814     PetscCall(MatProductCreate(A, B, NULL, C));
9815     PetscCall(MatProductSetType(*C, ptype));
9816     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9817     PetscCall(MatProductSetFill(*C, fill));
9818 
9819     (*C)->product->api_user = PETSC_TRUE;
9820     PetscCall(MatProductSetFromOptions(*C));
9821     PetscCall(MatProductSymbolic(*C));
9822   } else { /* scall == MAT_REUSE_MATRIX */
9823     Mat_Product *product = (*C)->product;
9824     PetscBool    isdense;
9825 
9826     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9827     if (isdense && product && product->type != ptype) {
9828       PetscCall(MatProductClear(*C));
9829       product = NULL;
9830     }
9831     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9832     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9833       if (isdense) {
9834         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9835         product           = (*C)->product;
9836         product->fill     = fill;
9837         product->api_user = PETSC_TRUE;
9838         product->clear    = PETSC_TRUE;
9839 
9840         PetscCall(MatProductSetType(*C, ptype));
9841         PetscCall(MatProductSetFromOptions(*C));
9842         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);
9843         PetscCall(MatProductSymbolic(*C));
9844       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9845     } else { /* user may change input matrices A or B when REUSE */
9846       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9847     }
9848   }
9849   PetscCall(MatProductNumeric(*C));
9850   PetscFunctionReturn(0);
9851 }
9852 
9853 /*@
9854    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9855 
9856    Neighbor-wise Collective on A
9857 
9858    Input Parameters:
9859 +  A - the left matrix
9860 .  B - the right matrix
9861 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9862 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9863           if the result is a dense matrix this is irrelevant
9864 
9865    Output Parameters:
9866 .  C - the product matrix
9867 
9868    Notes:
9869    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9870 
9871    `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
9872    call to this function with `MAT_INITIAL_MATRIX`.
9873 
9874    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9875 
9876    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`,
9877    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9878 
9879    Example of Usage:
9880 .vb
9881      MatProductCreate(A,B,NULL,&C);
9882      MatProductSetType(C,MATPRODUCT_AB);
9883      MatProductSymbolic(C);
9884      MatProductNumeric(C); // compute C=A * B
9885      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9886      MatProductNumeric(C);
9887      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9888      MatProductNumeric(C);
9889 .ve
9890 
9891    Level: intermediate
9892 
9893 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9894 @*/
9895 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9896 {
9897   PetscFunctionBegin;
9898   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9899   PetscFunctionReturn(0);
9900 }
9901 
9902 /*@
9903    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9904 
9905    Neighbor-wise Collective on A
9906 
9907    Input Parameters:
9908 +  A - the left matrix
9909 .  B - the right matrix
9910 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9911 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9912 
9913    Output Parameters:
9914 .  C - the product matrix
9915 
9916    Notes:
9917    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9918 
9919    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9920 
9921    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9922    actually needed.
9923 
9924    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9925    and for pairs of `MATMPIDENSE` matrices.
9926 
9927    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9928 
9929    Options Database Keys:
9930 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9931               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9932               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9933 
9934    Level: intermediate
9935 
9936 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9937 @*/
9938 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9939 {
9940   PetscFunctionBegin;
9941   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9942   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9943   PetscFunctionReturn(0);
9944 }
9945 
9946 /*@
9947    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9948 
9949    Neighbor-wise Collective on A
9950 
9951    Input Parameters:
9952 +  A - the left matrix
9953 .  B - the right matrix
9954 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9955 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9956 
9957    Output Parameters:
9958 .  C - the product matrix
9959 
9960    Notes:
9961    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9962 
9963    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9964 
9965    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9966 
9967    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9968    actually needed.
9969 
9970    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9971    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
9972 
9973    Level: intermediate
9974 
9975 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9976 @*/
9977 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9978 {
9979   PetscFunctionBegin;
9980   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
9981   PetscFunctionReturn(0);
9982 }
9983 
9984 /*@
9985    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9986 
9987    Neighbor-wise Collective on A
9988 
9989    Input Parameters:
9990 +  A - the left matrix
9991 .  B - the middle matrix
9992 .  C - the right matrix
9993 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9994 -  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
9995           if the result is a dense matrix this is irrelevant
9996 
9997    Output Parameters:
9998 .  D - the product matrix
9999 
10000    Notes:
10001    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10002 
10003    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10004 
10005    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10006 
10007    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10008    actually needed.
10009 
10010    If you have many matrices with the same non-zero structure to multiply, you
10011    should use `MAT_REUSE_MATRIX` in all calls but the first
10012 
10013    Level: intermediate
10014 
10015 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10016 @*/
10017 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10018 {
10019   PetscFunctionBegin;
10020   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10021   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10022 
10023   if (scall == MAT_INITIAL_MATRIX) {
10024     PetscCall(MatProductCreate(A, B, C, D));
10025     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10026     PetscCall(MatProductSetAlgorithm(*D, "default"));
10027     PetscCall(MatProductSetFill(*D, fill));
10028 
10029     (*D)->product->api_user = PETSC_TRUE;
10030     PetscCall(MatProductSetFromOptions(*D));
10031     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,
10032                ((PetscObject)C)->type_name);
10033     PetscCall(MatProductSymbolic(*D));
10034   } else { /* user may change input matrices when REUSE */
10035     PetscCall(MatProductReplaceMats(A, B, C, *D));
10036   }
10037   PetscCall(MatProductNumeric(*D));
10038   PetscFunctionReturn(0);
10039 }
10040 
10041 /*@
10042    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10043 
10044    Collective on mat
10045 
10046    Input Parameters:
10047 +  mat - the matrix
10048 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10049 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10050 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10051 
10052    Output Parameter:
10053 .  matredundant - redundant matrix
10054 
10055    Notes:
10056    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10057    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10058 
10059    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10060    calling it.
10061 
10062    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10063 
10064    Level: advanced
10065 
10066 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10067 @*/
10068 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10069 {
10070   MPI_Comm       comm;
10071   PetscMPIInt    size;
10072   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10073   Mat_Redundant *redund     = NULL;
10074   PetscSubcomm   psubcomm   = NULL;
10075   MPI_Comm       subcomm_in = subcomm;
10076   Mat           *matseq;
10077   IS             isrow, iscol;
10078   PetscBool      newsubcomm = PETSC_FALSE;
10079 
10080   PetscFunctionBegin;
10081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10082   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10083     PetscValidPointer(*matredundant, 5);
10084     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10085   }
10086 
10087   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10088   if (size == 1 || nsubcomm == 1) {
10089     if (reuse == MAT_INITIAL_MATRIX) {
10090       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10091     } else {
10092       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");
10093       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10094     }
10095     PetscFunctionReturn(0);
10096   }
10097 
10098   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10099   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10100   MatCheckPreallocated(mat, 1);
10101 
10102   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10103   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10104     /* create psubcomm, then get subcomm */
10105     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10106     PetscCallMPI(MPI_Comm_size(comm, &size));
10107     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10108 
10109     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10110     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10111     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10112     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10113     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10114     newsubcomm = PETSC_TRUE;
10115     PetscCall(PetscSubcommDestroy(&psubcomm));
10116   }
10117 
10118   /* get isrow, iscol and a local sequential matrix matseq[0] */
10119   if (reuse == MAT_INITIAL_MATRIX) {
10120     mloc_sub = PETSC_DECIDE;
10121     nloc_sub = PETSC_DECIDE;
10122     if (bs < 1) {
10123       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10124       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10125     } else {
10126       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10127       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10128     }
10129     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10130     rstart = rend - mloc_sub;
10131     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10132     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10133   } else { /* reuse == MAT_REUSE_MATRIX */
10134     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");
10135     /* retrieve subcomm */
10136     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10137     redund = (*matredundant)->redundant;
10138     isrow  = redund->isrow;
10139     iscol  = redund->iscol;
10140     matseq = redund->matseq;
10141   }
10142   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10143 
10144   /* get matredundant over subcomm */
10145   if (reuse == MAT_INITIAL_MATRIX) {
10146     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10147 
10148     /* create a supporting struct and attach it to C for reuse */
10149     PetscCall(PetscNew(&redund));
10150     (*matredundant)->redundant = redund;
10151     redund->isrow              = isrow;
10152     redund->iscol              = iscol;
10153     redund->matseq             = matseq;
10154     if (newsubcomm) {
10155       redund->subcomm = subcomm;
10156     } else {
10157       redund->subcomm = MPI_COMM_NULL;
10158     }
10159   } else {
10160     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10161   }
10162 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10163   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10164     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10165     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10166   }
10167 #endif
10168   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10169   PetscFunctionReturn(0);
10170 }
10171 
10172 /*@C
10173    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10174    a given `Mat`. Each submatrix can span multiple procs.
10175 
10176    Collective on mat
10177 
10178    Input Parameters:
10179 +  mat - the matrix
10180 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
10181 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10182 
10183    Output Parameter:
10184 .  subMat - 'parallel submatrices each spans a given subcomm
10185 
10186   Notes:
10187   The submatrix partition across processors is dictated by 'subComm' a
10188   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
10189   is not restriced to be grouped with consecutive original ranks.
10190 
10191   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10192   map directly to the layout of the original matrix [wrt the local
10193   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10194   into the 'DiagonalMat' of the subMat, hence it is used directly from
10195   the subMat. However the offDiagMat looses some columns - and this is
10196   reconstructed with `MatSetValues()`
10197 
10198   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10199 
10200   Level: advanced
10201 
10202 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10203 @*/
10204 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10205 {
10206   PetscMPIInt commsize, subCommSize;
10207 
10208   PetscFunctionBegin;
10209   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10210   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10211   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10212 
10213   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");
10214   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10215   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10216   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10217   PetscFunctionReturn(0);
10218 }
10219 
10220 /*@
10221    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10222 
10223    Not Collective
10224 
10225    Input Parameters:
10226 +  mat - matrix to extract local submatrix from
10227 .  isrow - local row indices for submatrix
10228 -  iscol - local column indices for submatrix
10229 
10230    Output Parameter:
10231 .  submat - the submatrix
10232 
10233    Level: intermediate
10234 
10235    Notes:
10236    The submat should be returned with `MatRestoreLocalSubMatrix()`.
10237 
10238    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10239    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10240 
10241    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10242    `MatSetValuesBlockedLocal()` will also be implemented.
10243 
10244    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10245    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10246 
10247 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10248 @*/
10249 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10250 {
10251   PetscFunctionBegin;
10252   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10253   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10254   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10255   PetscCheckSameComm(isrow, 2, iscol, 3);
10256   PetscValidPointer(submat, 4);
10257   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10258 
10259   if (mat->ops->getlocalsubmatrix) {
10260     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10261   } else {
10262     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10263   }
10264   PetscFunctionReturn(0);
10265 }
10266 
10267 /*@
10268    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10269 
10270    Not Collective
10271 
10272    Input Parameters:
10273 +  mat - matrix to extract local submatrix from
10274 .  isrow - local row indices for submatrix
10275 .  iscol - local column indices for submatrix
10276 -  submat - the submatrix
10277 
10278    Level: intermediate
10279 
10280 .seealso: `MatGetLocalSubMatrix()`
10281 @*/
10282 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10283 {
10284   PetscFunctionBegin;
10285   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10286   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10287   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10288   PetscCheckSameComm(isrow, 2, iscol, 3);
10289   PetscValidPointer(submat, 4);
10290   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10291 
10292   if (mat->ops->restorelocalsubmatrix) {
10293     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10294   } else {
10295     PetscCall(MatDestroy(submat));
10296   }
10297   *submat = NULL;
10298   PetscFunctionReturn(0);
10299 }
10300 
10301 /* --------------------------------------------------------*/
10302 /*@
10303    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10304 
10305    Collective on mat
10306 
10307    Input Parameter:
10308 .  mat - the matrix
10309 
10310    Output Parameter:
10311 .  is - if any rows have zero diagonals this contains the list of them
10312 
10313    Level: developer
10314 
10315 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10316 @*/
10317 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10318 {
10319   PetscFunctionBegin;
10320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10321   PetscValidType(mat, 1);
10322   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10323   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10324 
10325   if (!mat->ops->findzerodiagonals) {
10326     Vec                diag;
10327     const PetscScalar *a;
10328     PetscInt          *rows;
10329     PetscInt           rStart, rEnd, r, nrow = 0;
10330 
10331     PetscCall(MatCreateVecs(mat, &diag, NULL));
10332     PetscCall(MatGetDiagonal(mat, diag));
10333     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10334     PetscCall(VecGetArrayRead(diag, &a));
10335     for (r = 0; r < rEnd - rStart; ++r)
10336       if (a[r] == 0.0) ++nrow;
10337     PetscCall(PetscMalloc1(nrow, &rows));
10338     nrow = 0;
10339     for (r = 0; r < rEnd - rStart; ++r)
10340       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10341     PetscCall(VecRestoreArrayRead(diag, &a));
10342     PetscCall(VecDestroy(&diag));
10343     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10344   } else {
10345     PetscUseTypeMethod(mat, findzerodiagonals, is);
10346   }
10347   PetscFunctionReturn(0);
10348 }
10349 
10350 /*@
10351    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10352 
10353    Collective on mat
10354 
10355    Input Parameter:
10356 .  mat - the matrix
10357 
10358    Output Parameter:
10359 .  is - contains the list of rows with off block diagonal entries
10360 
10361    Level: developer
10362 
10363 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10364 @*/
10365 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10366 {
10367   PetscFunctionBegin;
10368   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10369   PetscValidType(mat, 1);
10370   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10371   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10372 
10373   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10374   PetscFunctionReturn(0);
10375 }
10376 
10377 /*@C
10378   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10379 
10380   Collective on mat
10381 
10382   Input Parameters:
10383 . mat - the matrix
10384 
10385   Output Parameters:
10386 . values - the block inverses in column major order (FORTRAN-like)
10387 
10388    Notes:
10389    The size of the blocks is determined by the block size of the matrix.
10390 
10391    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10392 
10393    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10394 
10395    Fortran Note:
10396      This routine is not available from Fortran.
10397 
10398   Level: advanced
10399 
10400 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10401 @*/
10402 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10403 {
10404   PetscFunctionBegin;
10405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10406   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10407   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10408   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10409   PetscFunctionReturn(0);
10410 }
10411 
10412 /*@C
10413   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10414 
10415   Collective on mat
10416 
10417   Input Parameters:
10418 + mat - the matrix
10419 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10420 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10421 
10422   Output Parameters:
10423 . values - the block inverses in column major order (FORTRAN-like)
10424 
10425   Notes:
10426   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10427 
10428   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10429 
10430   Fortran Note:
10431   This routine is not available from Fortran.
10432 
10433   Level: advanced
10434 
10435 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10436 @*/
10437 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10438 {
10439   PetscFunctionBegin;
10440   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10441   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10442   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10443   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10444   PetscFunctionReturn(0);
10445 }
10446 
10447 /*@
10448   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10449 
10450   Collective on Mat
10451 
10452   Input Parameters:
10453 + A - the matrix
10454 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10455 
10456   Note:
10457   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10458 
10459   Level: advanced
10460 
10461 .seealso: `MatInvertBlockDiagonal()`
10462 @*/
10463 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10464 {
10465   const PetscScalar *vals;
10466   PetscInt          *dnnz;
10467   PetscInt           m, rstart, rend, bs, i, j;
10468 
10469   PetscFunctionBegin;
10470   PetscCall(MatInvertBlockDiagonal(A, &vals));
10471   PetscCall(MatGetBlockSize(A, &bs));
10472   PetscCall(MatGetLocalSize(A, &m, NULL));
10473   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10474   PetscCall(PetscMalloc1(m / bs, &dnnz));
10475   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10476   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10477   PetscCall(PetscFree(dnnz));
10478   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10479   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10480   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10481   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10482   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10483   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10484   PetscFunctionReturn(0);
10485 }
10486 
10487 /*@C
10488     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10489     via `MatTransposeColoringCreate()`.
10490 
10491     Collective on c
10492 
10493     Input Parameter:
10494 .   c - coloring context
10495 
10496     Level: intermediate
10497 
10498 .seealso: `MatTransposeColoringCreate()`
10499 @*/
10500 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10501 {
10502   MatTransposeColoring matcolor = *c;
10503 
10504   PetscFunctionBegin;
10505   if (!matcolor) PetscFunctionReturn(0);
10506   if (--((PetscObject)matcolor)->refct > 0) {
10507     matcolor = NULL;
10508     PetscFunctionReturn(0);
10509   }
10510 
10511   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10512   PetscCall(PetscFree(matcolor->rows));
10513   PetscCall(PetscFree(matcolor->den2sp));
10514   PetscCall(PetscFree(matcolor->colorforcol));
10515   PetscCall(PetscFree(matcolor->columns));
10516   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10517   PetscCall(PetscHeaderDestroy(c));
10518   PetscFunctionReturn(0);
10519 }
10520 
10521 /*@C
10522     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10523     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10524     `MatTransposeColoring` to sparse B.
10525 
10526     Collective on coloring
10527 
10528     Input Parameters:
10529 +   B - sparse matrix B
10530 .   Btdense - symbolic dense matrix B^T
10531 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10532 
10533     Output Parameter:
10534 .   Btdense - dense matrix B^T
10535 
10536     Level: developer
10537 
10538     Note:
10539     These are used internally for some implementations of `MatRARt()`
10540 
10541 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10542 
10543 @*/
10544 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10545 {
10546   PetscFunctionBegin;
10547   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10548   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10549   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10550 
10551   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10552   PetscFunctionReturn(0);
10553 }
10554 
10555 /*@C
10556     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10557     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10558     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10559     Csp from Cden.
10560 
10561     Collective on matcoloring
10562 
10563     Input Parameters:
10564 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10565 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10566 
10567     Output Parameter:
10568 .   Csp - sparse matrix
10569 
10570     Level: developer
10571 
10572     Note:
10573     These are used internally for some implementations of `MatRARt()`
10574 
10575 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10576 
10577 @*/
10578 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10579 {
10580   PetscFunctionBegin;
10581   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10582   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10583   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10584 
10585   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10586   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10587   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10588   PetscFunctionReturn(0);
10589 }
10590 
10591 /*@C
10592    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10593 
10594    Collective on mat
10595 
10596    Input Parameters:
10597 +  mat - the matrix product C
10598 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10599 
10600     Output Parameter:
10601 .   color - the new coloring context
10602 
10603     Level: intermediate
10604 
10605 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10606           `MatTransColoringApplyDenToSp()`
10607 @*/
10608 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10609 {
10610   MatTransposeColoring c;
10611   MPI_Comm             comm;
10612 
10613   PetscFunctionBegin;
10614   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10615   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10616   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10617 
10618   c->ctype = iscoloring->ctype;
10619   if (mat->ops->transposecoloringcreate) {
10620     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10621   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10622 
10623   *color = c;
10624   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10625   PetscFunctionReturn(0);
10626 }
10627 
10628 /*@
10629       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10630         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10631         same, otherwise it will be larger
10632 
10633      Not Collective
10634 
10635   Input Parameter:
10636 .    A  - the matrix
10637 
10638   Output Parameter:
10639 .    state - the current state
10640 
10641   Notes:
10642     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10643          different matrices
10644 
10645     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10646 
10647     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10648 
10649   Level: intermediate
10650 
10651 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10652 @*/
10653 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10654 {
10655   PetscFunctionBegin;
10656   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10657   *state = mat->nonzerostate;
10658   PetscFunctionReturn(0);
10659 }
10660 
10661 /*@
10662       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10663                  matrices from each processor
10664 
10665     Collective
10666 
10667    Input Parameters:
10668 +    comm - the communicators the parallel matrix will live on
10669 .    seqmat - the input sequential matrices
10670 .    n - number of local columns (or `PETSC_DECIDE`)
10671 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10672 
10673    Output Parameter:
10674 .    mpimat - the parallel matrix generated
10675 
10676     Level: developer
10677 
10678    Note:
10679     The number of columns of the matrix in EACH processor MUST be the same.
10680 
10681 .seealso: `Mat`
10682 @*/
10683 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10684 {
10685   PetscMPIInt size;
10686 
10687   PetscFunctionBegin;
10688   PetscCallMPI(MPI_Comm_size(comm, &size));
10689   if (size == 1) {
10690     if (reuse == MAT_INITIAL_MATRIX) {
10691       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10692     } else {
10693       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10694     }
10695     PetscFunctionReturn(0);
10696   }
10697 
10698   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");
10699 
10700   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10701   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10702   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10703   PetscFunctionReturn(0);
10704 }
10705 
10706 /*@
10707      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10708 
10709     Collective on A
10710 
10711    Input Parameters:
10712 +    A   - the matrix to create subdomains from
10713 -    N   - requested number of subdomains
10714 
10715    Output Parameters:
10716 +    n   - number of subdomains resulting on this rank
10717 -    iss - `IS` list with indices of subdomains on this rank
10718 
10719     Level: advanced
10720 
10721     Note:
10722     The number of subdomains must be smaller than the communicator size
10723 
10724 .seealso: `Mat`, `IS`
10725 @*/
10726 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10727 {
10728   MPI_Comm    comm, subcomm;
10729   PetscMPIInt size, rank, color;
10730   PetscInt    rstart, rend, k;
10731 
10732   PetscFunctionBegin;
10733   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10734   PetscCallMPI(MPI_Comm_size(comm, &size));
10735   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10736   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);
10737   *n    = 1;
10738   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10739   color = rank / k;
10740   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10741   PetscCall(PetscMalloc1(1, iss));
10742   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10743   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10744   PetscCallMPI(MPI_Comm_free(&subcomm));
10745   PetscFunctionReturn(0);
10746 }
10747 
10748 /*@
10749    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10750 
10751    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10752    If they are not the same, uses `MatMatMatMult()`.
10753 
10754    Once the coarse grid problem is constructed, correct for interpolation operators
10755    that are not of full rank, which can legitimately happen in the case of non-nested
10756    geometric multigrid.
10757 
10758    Input Parameters:
10759 +  restrct - restriction operator
10760 .  dA - fine grid matrix
10761 .  interpolate - interpolation operator
10762 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10763 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10764 
10765    Output Parameters:
10766 .  A - the Galerkin coarse matrix
10767 
10768    Options Database Key:
10769 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10770 
10771    Level: developer
10772 
10773 .seealso: `MatPtAP()`, `MatMatMatMult()`
10774 @*/
10775 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10776 {
10777   IS  zerorows;
10778   Vec diag;
10779 
10780   PetscFunctionBegin;
10781   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10782   /* Construct the coarse grid matrix */
10783   if (interpolate == restrct) {
10784     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10785   } else {
10786     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10787   }
10788 
10789   /* If the interpolation matrix is not of full rank, A will have zero rows.
10790      This can legitimately happen in the case of non-nested geometric multigrid.
10791      In that event, we set the rows of the matrix to the rows of the identity,
10792      ignoring the equations (as the RHS will also be zero). */
10793 
10794   PetscCall(MatFindZeroRows(*A, &zerorows));
10795 
10796   if (zerorows != NULL) { /* if there are any zero rows */
10797     PetscCall(MatCreateVecs(*A, &diag, NULL));
10798     PetscCall(MatGetDiagonal(*A, diag));
10799     PetscCall(VecISSet(diag, zerorows, 1.0));
10800     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10801     PetscCall(VecDestroy(&diag));
10802     PetscCall(ISDestroy(&zerorows));
10803   }
10804   PetscFunctionReturn(0);
10805 }
10806 
10807 /*@C
10808     MatSetOperation - Allows user to set a matrix operation for any matrix type
10809 
10810    Logically Collective on mat
10811 
10812     Input Parameters:
10813 +   mat - the matrix
10814 .   op - the name of the operation
10815 -   f - the function that provides the operation
10816 
10817    Level: developer
10818 
10819     Usage:
10820 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10821 $      PetscCall(MatCreateXXX(comm,...&A);
10822 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10823 
10824     Notes:
10825     See the file include/petscmat.h for a complete list of matrix
10826     operations, which all have the form MATOP_<OPERATION>, where
10827     <OPERATION> is the name (in all capital letters) of the
10828     user interface routine (e.g., MatMult() -> MATOP_MULT).
10829 
10830     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10831     sequence as the usual matrix interface routines, since they
10832     are intended to be accessed via the usual matrix interface
10833     routines, e.g.,
10834 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10835 
10836     In particular each function MUST return an error code of 0 on success and
10837     nonzero on failure.
10838 
10839     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10840 
10841 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10842 @*/
10843 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10844 {
10845   PetscFunctionBegin;
10846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10847   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10848   (((void (**)(void))mat->ops)[op]) = f;
10849   PetscFunctionReturn(0);
10850 }
10851 
10852 /*@C
10853     MatGetOperation - Gets a matrix operation for any matrix type.
10854 
10855     Not Collective
10856 
10857     Input Parameters:
10858 +   mat - the matrix
10859 -   op - the name of the operation
10860 
10861     Output Parameter:
10862 .   f - the function that provides the operation
10863 
10864     Level: developer
10865 
10866     Usage:
10867 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10868 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10869 
10870     Notes:
10871     See the file include/petscmat.h for a complete list of matrix
10872     operations, which all have the form MATOP_<OPERATION>, where
10873     <OPERATION> is the name (in all capital letters) of the
10874     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10875 
10876     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10877 
10878 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10879 @*/
10880 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10881 {
10882   PetscFunctionBegin;
10883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10884   *f = (((void (**)(void))mat->ops)[op]);
10885   PetscFunctionReturn(0);
10886 }
10887 
10888 /*@
10889     MatHasOperation - Determines whether the given matrix supports the particular operation.
10890 
10891    Not Collective
10892 
10893    Input Parameters:
10894 +  mat - the matrix
10895 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10896 
10897    Output Parameter:
10898 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10899 
10900    Level: advanced
10901 
10902    Note:
10903    See the file include/petscmat.h for a complete list of matrix
10904    operations, which all have the form MATOP_<OPERATION>, where
10905    <OPERATION> is the name (in all capital letters) of the
10906    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10907 
10908 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10909 @*/
10910 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10911 {
10912   PetscFunctionBegin;
10913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10914   PetscValidBoolPointer(has, 3);
10915   if (mat->ops->hasoperation) {
10916     PetscUseTypeMethod(mat, hasoperation, op, has);
10917   } else {
10918     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10919     else {
10920       *has = PETSC_FALSE;
10921       if (op == MATOP_CREATE_SUBMATRIX) {
10922         PetscMPIInt size;
10923 
10924         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10925         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10926       }
10927     }
10928   }
10929   PetscFunctionReturn(0);
10930 }
10931 
10932 /*@
10933     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10934 
10935    Collective on mat
10936 
10937    Input Parameters:
10938 .  mat - the matrix
10939 
10940    Output Parameter:
10941 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10942 
10943    Level: beginner
10944 
10945 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10946 @*/
10947 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10948 {
10949   PetscFunctionBegin;
10950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10951   PetscValidType(mat, 1);
10952   PetscValidBoolPointer(cong, 2);
10953   if (!mat->rmap || !mat->cmap) {
10954     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10955     PetscFunctionReturn(0);
10956   }
10957   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10958     PetscCall(PetscLayoutSetUp(mat->rmap));
10959     PetscCall(PetscLayoutSetUp(mat->cmap));
10960     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10961     if (*cong) mat->congruentlayouts = 1;
10962     else mat->congruentlayouts = 0;
10963   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10964   PetscFunctionReturn(0);
10965 }
10966 
10967 PetscErrorCode MatSetInf(Mat A)
10968 {
10969   PetscFunctionBegin;
10970   PetscUseTypeMethod(A, setinf);
10971   PetscFunctionReturn(0);
10972 }
10973 
10974 /*C
10975    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
10976    and possibly removes small values from the graph structure.
10977 
10978    Collective on mat
10979 
10980    Input Parameters:
10981 +  A - the matrix
10982 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
10983 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
10984 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
10985 
10986    Output Parameter:
10987 .  graph - the resulting graph
10988 
10989    Level: advanced
10990 
10991 .seealso: `MatCreate()`, `PCGAMG`
10992 */
10993 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
10994 {
10995   PetscFunctionBegin;
10996   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
10997   PetscValidType(A, 1);
10998   PetscValidPointer(graph, 3);
10999   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11000   PetscFunctionReturn(0);
11001 }
11002