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