xref: /petsc/src/mat/interface/matrix.c (revision 7c441f3aff93c611491d4ea0564d57010b1fd4e9)
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
46 
47 /*@
48    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,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
73 {
74   PetscRandom randObj = NULL;
75 
76   PetscFunctionBegin;
77   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
78   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
79   PetscValidType(x, 1);
80   MatCheckPreallocated(x, 1);
81 
82   if (!rctx) {
83     MPI_Comm comm;
84     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
85     PetscCall(PetscRandomCreate(comm, &randObj));
86     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
87     PetscCall(PetscRandomSetFromOptions(randObj));
88     rctx = randObj;
89   }
90   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
91   PetscUseTypeMethod(x, setrandom, rctx);
92   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
93 
94   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
95   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
96   PetscCall(PetscRandomDestroy(&randObj));
97   PetscFunctionReturn(0);
98 }
99 
100 /*@
101    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
102 
103    Logically Collective on mat
104 
105    Input Parameter:
106 .  mat - the factored matrix
107 
108    Output Parameters:
109 +  pivot - the pivot value computed
110 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
111          the share the matrix
112 
113    Level: advanced
114 
115    Notes:
116     This routine does not work for factorizations done with external packages.
117 
118     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
119 
120     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
121 
122 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
123           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
124 @*/
125 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
126 {
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
129   PetscValidRealPointer(pivot, 2);
130   PetscValidIntPointer(row, 3);
131   *pivot = mat->factorerror_zeropivot_value;
132   *row   = mat->factorerror_zeropivot_row;
133   PetscFunctionReturn(0);
134 }
135 
136 /*@
137    MatFactorGetError - gets the error code from a factorization
138 
139    Logically Collective on mat
140 
141    Input Parameters:
142 .  mat - the factored matrix
143 
144    Output Parameter:
145 .  err  - the error code
146 
147    Level: advanced
148 
149    Note:
150     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
151 
152 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
153           `MatFactorError`
154 @*/
155 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
156 {
157   PetscFunctionBegin;
158   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
159   PetscValidPointer(err, 2);
160   *err = mat->factorerrortype;
161   PetscFunctionReturn(0);
162 }
163 
164 /*@
165    MatFactorClearError - clears the error code in a factorization
166 
167    Logically Collective on mat
168 
169    Input Parameter:
170 .  mat - the factored matrix
171 
172    Level: developer
173 
174    Note:
175     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
176 
177 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
178           `MatGetErrorCode()`, `MatFactorError`
179 @*/
180 PetscErrorCode MatFactorClearError(Mat mat)
181 {
182   PetscFunctionBegin;
183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
184   mat->factorerrortype             = MAT_FACTOR_NOERROR;
185   mat->factorerror_zeropivot_value = 0.0;
186   mat->factorerror_zeropivot_row   = 0;
187   PetscFunctionReturn(0);
188 }
189 
190 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
191 {
192   Vec                r, l;
193   const PetscScalar *al;
194   PetscInt           i, nz, gnz, N, n;
195 
196   PetscFunctionBegin;
197   PetscCall(MatCreateVecs(mat, &r, &l));
198   if (!cols) { /* nonzero rows */
199     PetscCall(MatGetSize(mat, &N, NULL));
200     PetscCall(MatGetLocalSize(mat, &n, NULL));
201     PetscCall(VecSet(l, 0.0));
202     PetscCall(VecSetRandom(r, NULL));
203     PetscCall(MatMult(mat, r, l));
204     PetscCall(VecGetArrayRead(l, &al));
205   } else { /* nonzero columns */
206     PetscCall(MatGetSize(mat, NULL, &N));
207     PetscCall(MatGetLocalSize(mat, NULL, &n));
208     PetscCall(VecSet(r, 0.0));
209     PetscCall(VecSetRandom(l, NULL));
210     PetscCall(MatMultTranspose(mat, l, r));
211     PetscCall(VecGetArrayRead(r, &al));
212   }
213   if (tol <= 0.0) {
214     for (i = 0, nz = 0; i < n; i++)
215       if (al[i] != 0.0) nz++;
216   } else {
217     for (i = 0, nz = 0; i < n; i++)
218       if (PetscAbsScalar(al[i]) > tol) nz++;
219   }
220   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
221   if (gnz != N) {
222     PetscInt *nzr;
223     PetscCall(PetscMalloc1(nz, &nzr));
224     if (nz) {
225       if (tol < 0) {
226         for (i = 0, nz = 0; i < n; i++)
227           if (al[i] != 0.0) nzr[nz++] = i;
228       } else {
229         for (i = 0, nz = 0; i < n; i++)
230           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
231       }
232     }
233     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
234   } else *nonzero = NULL;
235   if (!cols) { /* nonzero rows */
236     PetscCall(VecRestoreArrayRead(l, &al));
237   } else {
238     PetscCall(VecRestoreArrayRead(r, &al));
239   }
240   PetscCall(VecDestroy(&l));
241   PetscCall(VecDestroy(&r));
242   PetscFunctionReturn(0);
243 }
244 
245 /*@
246       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
247 
248   Input Parameter:
249 .    A  - the matrix
250 
251   Output Parameter:
252 .    keptrows - the rows that are not completely zero
253 
254   Note:
255     keptrows is set to NULL if all rows are nonzero.
256 
257   Level: intermediate
258 
259 .seealso: `Mat`, `MatFindZeroRows()`
260  @*/
261 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
262 {
263   PetscFunctionBegin;
264   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
265   PetscValidType(mat, 1);
266   PetscValidPointer(keptrows, 2);
267   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
268   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
269   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
270   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
271   PetscFunctionReturn(0);
272 }
273 
274 /*@
275       MatFindZeroRows - Locate all rows that are completely zero in the matrix
276 
277   Input Parameter:
278 .    A  - the matrix
279 
280   Output Parameter:
281 .    zerorows - the rows that are completely zero
282 
283   Note:
284     zerorows is set to NULL if no rows are zero.
285 
286   Level: intermediate
287 
288 .seealso: `Mat`, `MatFindNonzeroRows()`
289  @*/
290 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
291 {
292   IS       keptrows;
293   PetscInt m, n;
294 
295   PetscFunctionBegin;
296   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
297   PetscValidType(mat, 1);
298   PetscValidPointer(zerorows, 2);
299   PetscCall(MatFindNonzeroRows(mat, &keptrows));
300   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
301      In keeping with this convention, we set zerorows to NULL if there are no zero
302      rows. */
303   if (keptrows == NULL) {
304     *zerorows = NULL;
305   } else {
306     PetscCall(MatGetOwnershipRange(mat, &m, &n));
307     PetscCall(ISComplement(keptrows, m, n, zerorows));
308     PetscCall(ISDestroy(&keptrows));
309   }
310   PetscFunctionReturn(0);
311 }
312 
313 /*@
314    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
315 
316    Not Collective
317 
318    Input Parameters:
319 .   A - the matrix
320 
321    Output Parameters:
322 .   a - the diagonal part (which is a SEQUENTIAL matrix)
323 
324    Notes:
325    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
326 
327    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.
328 
329    Level: advanced
330 
331 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
332 @*/
333 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
334 {
335   PetscFunctionBegin;
336   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
337   PetscValidType(A, 1);
338   PetscValidPointer(a, 2);
339   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
340   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
341   else {
342     PetscMPIInt size;
343 
344     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
345     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
346     *a = A;
347   }
348   PetscFunctionReturn(0);
349 }
350 
351 /*@
352    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
353 
354    Collective on mat
355 
356    Input Parameters:
357 .  mat - the matrix
358 
359    Output Parameter:
360 .   trace - the sum of the diagonal entries
361 
362    Level: advanced
363 
364 .seealso: `Mat`
365 @*/
366 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
367 {
368   Vec diag;
369 
370   PetscFunctionBegin;
371   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
372   PetscValidScalarPointer(trace, 2);
373   PetscCall(MatCreateVecs(mat, &diag, NULL));
374   PetscCall(MatGetDiagonal(mat, diag));
375   PetscCall(VecSum(diag, trace));
376   PetscCall(VecDestroy(&diag));
377   PetscFunctionReturn(0);
378 }
379 
380 /*@
381    MatRealPart - Zeros out the imaginary part of the matrix
382 
383    Logically Collective on mat
384 
385    Input Parameters:
386 .  mat - the matrix
387 
388    Level: advanced
389 
390 .seealso: `MatImaginaryPart()`
391 @*/
392 PetscErrorCode MatRealPart(Mat mat)
393 {
394   PetscFunctionBegin;
395   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
396   PetscValidType(mat, 1);
397   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
398   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
399   MatCheckPreallocated(mat, 1);
400   PetscUseTypeMethod(mat, realpart);
401   PetscFunctionReturn(0);
402 }
403 
404 /*@C
405    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
406 
407    Collective on mat
408 
409    Input Parameter:
410 .  mat - the matrix
411 
412    Output Parameters:
413 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
414 -   ghosts - the global indices of the ghost points
415 
416    Note:
417     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
418 
419    Level: advanced
420 
421 .seealso: `Mat`, `VecCreateGhost()`
422 @*/
423 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
424 {
425   PetscFunctionBegin;
426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
427   PetscValidType(mat, 1);
428   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
429   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
430   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
431   else {
432     if (nghosts) *nghosts = 0;
433     if (ghosts) *ghosts = NULL;
434   }
435   PetscFunctionReturn(0);
436 }
437 
438 /*@
439    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
440 
441    Logically Collective on mat
442 
443    Input Parameters:
444 .  mat - the matrix
445 
446    Level: advanced
447 
448 .seealso: `MatRealPart()`
449 @*/
450 PetscErrorCode MatImaginaryPart(Mat mat)
451 {
452   PetscFunctionBegin;
453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
454   PetscValidType(mat, 1);
455   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
456   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
457   MatCheckPreallocated(mat, 1);
458   PetscUseTypeMethod(mat, imaginarypart);
459   PetscFunctionReturn(0);
460 }
461 
462 /*@
463    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
464 
465    Not Collective
466 
467    Input Parameter:
468 .  mat - the matrix
469 
470    Output Parameters:
471 +  missing - is any diagonal missing
472 -  dd - first diagonal entry that is missing (optional) on this process
473 
474    Level: advanced
475 
476 .seealso: `Mat`
477 @*/
478 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
479 {
480   PetscFunctionBegin;
481   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
482   PetscValidType(mat, 1);
483   PetscValidBoolPointer(missing, 2);
484   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
485   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
486   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
487   PetscFunctionReturn(0);
488 }
489 
490 /*@C
491    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
492    for each row that you get to ensure that your application does
493    not bleed memory.
494 
495    Not Collective
496 
497    Input Parameters:
498 +  mat - the matrix
499 -  row - the row to get
500 
501    Output Parameters:
502 +  ncols -  if not NULL, the number of nonzeros in the row
503 .  cols - if not NULL, the column numbers
504 -  vals - if not NULL, the values
505 
506    Notes:
507    This routine is provided for people who need to have direct access
508    to the structure of a matrix.  We hope that we provide enough
509    high-level matrix routines that few users will need it.
510 
511    `MatGetRow()` always returns 0-based column indices, regardless of
512    whether the internal representation is 0-based (default) or 1-based.
513 
514    For better efficiency, set cols and/or vals to NULL if you do
515    not wish to extract these quantities.
516 
517    The user can only examine the values extracted with `MatGetRow()`;
518    the values cannot be altered.  To change the matrix entries, one
519    must use `MatSetValues()`.
520 
521    You can only have one call to `MatGetRow()` outstanding for a particular
522    matrix at a time, per processor. `MatGetRow()` can only obtain rows
523    associated with the given processor, it cannot get rows from the
524    other processors; for that we suggest using `MatCreateSubMatrices()`, then
525    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
526    is in the global number of rows.
527 
528    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
529 
530    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
531 
532    Fortran Note:
533    The calling sequence from Fortran is
534 .vb
535    MatGetRow(matrix,row,ncols,cols,values,ierr)
536          Mat     matrix (input)
537          integer row    (input)
538          integer ncols  (output)
539          integer cols(maxcols) (output)
540          double precision (or double complex) values(maxcols) output
541 .ve
542    where maxcols >= maximum nonzeros in any row of the matrix.
543 
544    Caution:
545    Do not try to change the contents of the output arrays (cols and vals).
546    In some cases, this may corrupt the matrix.
547 
548    Level: advanced
549 
550 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
551 @*/
552 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
553 {
554   PetscInt incols;
555 
556   PetscFunctionBegin;
557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
558   PetscValidType(mat, 1);
559   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
560   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
561   MatCheckPreallocated(mat, 1);
562   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);
563   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
564   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
565   if (ncols) *ncols = incols;
566   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
567   PetscFunctionReturn(0);
568 }
569 
570 /*@
571    MatConjugate - replaces the matrix values with their complex conjugates
572 
573    Logically Collective on mat
574 
575    Input Parameters:
576 .  mat - the matrix
577 
578    Level: advanced
579 
580 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
581 @*/
582 PetscErrorCode MatConjugate(Mat mat)
583 {
584   PetscFunctionBegin;
585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
586   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
587   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
588     PetscUseTypeMethod(mat, conjugate);
589     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
590   }
591   PetscFunctionReturn(0);
592 }
593 
594 /*@C
595    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
596 
597    Not Collective
598 
599    Input Parameters:
600 +  mat - the matrix
601 .  row - the row to get
602 .  ncols, cols - the number of nonzeros and their columns
603 -  vals - if nonzero the column values
604 
605    Notes:
606    This routine should be called after you have finished examining the entries.
607 
608    This routine zeros out ncols, cols, and vals. This is to prevent accidental
609    us of the array after it has been restored. If you pass NULL, it will
610    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
611 
612    Fortran Notes:
613    The calling sequence from Fortran is
614 .vb
615    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
616       Mat     matrix (input)
617       integer row    (input)
618       integer ncols  (output)
619       integer cols(maxcols) (output)
620       double precision (or double complex) values(maxcols) output
621 .ve
622    Where maxcols >= maximum nonzeros in any row of the matrix.
623 
624    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
625    before another call to `MatGetRow()` can be made.
626 
627    Level: advanced
628 
629 .seealso: `MatGetRow()`
630 @*/
631 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
632 {
633   PetscFunctionBegin;
634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
635   if (ncols) PetscValidIntPointer(ncols, 3);
636   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
637   if (!mat->ops->restorerow) PetscFunctionReturn(0);
638   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
639   if (ncols) *ncols = 0;
640   if (cols) *cols = NULL;
641   if (vals) *vals = NULL;
642   PetscFunctionReturn(0);
643 }
644 
645 /*@
646    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
647    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
648 
649    Not Collective
650 
651    Input Parameters:
652 .  mat - the matrix
653 
654    Note:
655    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.
656 
657    Level: advanced
658 
659 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
660 @*/
661 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
662 {
663   PetscFunctionBegin;
664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
665   PetscValidType(mat, 1);
666   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
667   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
668   MatCheckPreallocated(mat, 1);
669   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
670   PetscUseTypeMethod(mat, getrowuppertriangular);
671   PetscFunctionReturn(0);
672 }
673 
674 /*@
675    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
676 
677    Not Collective
678 
679    Input Parameters:
680 .  mat - the matrix
681 
682    Note:
683    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
684 
685    Level: advanced
686 
687 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
688 @*/
689 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
690 {
691   PetscFunctionBegin;
692   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
693   PetscValidType(mat, 1);
694   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
695   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
696   MatCheckPreallocated(mat, 1);
697   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
698   PetscUseTypeMethod(mat, restorerowuppertriangular);
699   PetscFunctionReturn(0);
700 }
701 
702 /*@C
703    MatSetOptionsPrefix - Sets the prefix used for searching for all
704    `Mat` options in the database.
705 
706    Logically Collective on A
707 
708    Input Parameters:
709 +  A - the matrix
710 -  prefix - the prefix to prepend to all option names
711 
712    Notes:
713    A hyphen (-) must NOT be given at the beginning of the prefix name.
714    The first character of all runtime options is AUTOMATICALLY the hyphen.
715 
716    This is NOT used for options for the factorization of the matrix. Normally the
717    prefix is automatically passed in from the PC calling the factorization. To set
718    it directly use  `MatSetOptionsPrefixFactor()`
719 
720    Level: advanced
721 
722 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
723 @*/
724 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
725 {
726   PetscFunctionBegin;
727   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
728   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
729   PetscFunctionReturn(0);
730 }
731 
732 /*@C
733    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
734    for matrices created with `MatGetFactor()`
735 
736    Logically Collective on A
737 
738    Input Parameters:
739 +  A - the matrix
740 -  prefix - the prefix to prepend to all option names for the factored matrix
741 
742    Notes:
743    A hyphen (-) must NOT be given at the beginning of the prefix name.
744    The first character of all runtime options is AUTOMATICALLY the hyphen.
745 
746    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
747    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
748 
749    Level: developer
750 
751 .seealso:   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
752 @*/
753 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
754 {
755   PetscFunctionBegin;
756   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
757   if (prefix) {
758     PetscValidCharPointer(prefix, 2);
759     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
760     if (prefix != A->factorprefix) {
761       PetscCall(PetscFree(A->factorprefix));
762       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
763     }
764   } else PetscCall(PetscFree(A->factorprefix));
765   PetscFunctionReturn(0);
766 }
767 
768 /*@C
769    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
770    for matrices created with `MatGetFactor()`
771 
772    Logically Collective on A
773 
774    Input Parameters:
775 +  A - the matrix
776 -  prefix - the prefix to prepend to all option names for the factored matrix
777 
778    Notes:
779    A hyphen (-) must NOT be given at the beginning of the prefix name.
780    The first character of all runtime options is AUTOMATICALLY the hyphen.
781 
782    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
783    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
784 
785    Level: developer
786 
787 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
788           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
789           `MatSetOptionsPrefix()`
790 @*/
791 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
792 {
793   char  *buf = A->factorprefix;
794   size_t len1, len2;
795 
796   PetscFunctionBegin;
797   PetscValidHeader(A, 1);
798   if (!prefix) PetscFunctionReturn(0);
799   if (!buf) {
800     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
801     PetscFunctionReturn(0);
802   }
803   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
804 
805   PetscCall(PetscStrlen(prefix, &len1));
806   PetscCall(PetscStrlen(buf, &len2));
807   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
808   PetscCall(PetscStrcpy(A->factorprefix, buf));
809   PetscCall(PetscStrcat(A->factorprefix, prefix));
810   PetscCall(PetscFree(buf));
811   PetscFunctionReturn(0);
812 }
813 
814 /*@C
815    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
816    matrix options in the database.
817 
818    Logically Collective on A
819 
820    Input Parameters:
821 +  A - the matrix
822 -  prefix - the prefix to prepend to all option names
823 
824    Note:
825    A hyphen (-) must NOT be given at the beginning of the prefix name.
826    The first character of all runtime options is AUTOMATICALLY the hyphen.
827 
828    Level: advanced
829 
830 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
831 @*/
832 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
833 {
834   PetscFunctionBegin;
835   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
836   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
837   PetscFunctionReturn(0);
838 }
839 
840 /*@C
841    MatGetOptionsPrefix - Gets the prefix used for searching for all
842    matrix options in the database.
843 
844    Not Collective
845 
846    Input Parameter:
847 .  A - the matrix
848 
849    Output Parameter:
850 .  prefix - pointer to the prefix string used
851 
852    Fortran Note:
853     On the fortran side, the user should pass in a string 'prefix' of
854    sufficient length to hold the prefix.
855 
856    Level: advanced
857 
858 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
859 @*/
860 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
861 {
862   PetscFunctionBegin;
863   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
864   PetscValidPointer(prefix, 2);
865   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
866   PetscFunctionReturn(0);
867 }
868 
869 /*@
870    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
871 
872    Collective on A
873 
874    Input Parameters:
875 .  A - the matrix
876 
877    Notes:
878    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
879 
880    Users can reset the preallocation to access the original memory.
881 
882    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
883 
884    Level: beginner
885 
886 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
887 @*/
888 PetscErrorCode MatResetPreallocation(Mat A)
889 {
890   PetscFunctionBegin;
891   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
892   PetscValidType(A, 1);
893   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
894   PetscFunctionReturn(0);
895 }
896 
897 /*@
898    MatSetUp - Sets up the internal matrix data structures for later use.
899 
900    Collective on A
901 
902    Input Parameters:
903 .  A - the matrix
904 
905    Notes:
906    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
907 
908    If a suitable preallocation routine is used, this function does not need to be called.
909 
910    See the Performance chapter of the PETSc users manual for how to preallocate matrices
911 
912    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
913 
914    Level: intermediate
915 
916 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
917 @*/
918 PetscErrorCode MatSetUp(Mat A)
919 {
920   PetscFunctionBegin;
921   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
922   if (!((PetscObject)A)->type_name) {
923     PetscMPIInt size;
924 
925     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
926     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
927   }
928   if (!A->preallocated && A->ops->setup) {
929     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
930     PetscUseTypeMethod(A, setup);
931   }
932   PetscCall(PetscLayoutSetUp(A->rmap));
933   PetscCall(PetscLayoutSetUp(A->cmap));
934   A->preallocated = PETSC_TRUE;
935   PetscFunctionReturn(0);
936 }
937 
938 #if defined(PETSC_HAVE_SAWS)
939   #include <petscviewersaws.h>
940 #endif
941 
942 /*@C
943    MatViewFromOptions - View properties of the matrix from the options database
944 
945    Collective on A
946 
947    Input Parameters:
948 +  A - the matrix
949 .  obj - optional additional object that provides the options prefix to use
950 -  name - command line option
951 
952   Options Database:
953 .  -mat_view [viewertype]:... - the viewer and its options
954 
955   Notes:
956 .vb
957     If no value is provided ascii:stdout is used
958        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
959                                                   for example ascii::ascii_info prints just the information about the object not all details
960                                                   unless :append is given filename opens in write mode, overwriting what was already there
961        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
962        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
963        socket[:port]                             defaults to the standard output port
964        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
965 .ve
966 
967    Level: intermediate
968 
969 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
970 @*/
971 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
972 {
973   PetscFunctionBegin;
974   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
975   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
976   PetscFunctionReturn(0);
977 }
978 
979 /*@C
980    MatView - display information about a matrix in a variety ways
981 
982    Collective on mat
983 
984    Input Parameters:
985 +  mat - the matrix
986 -  viewer - visualization context
987 
988   Notes:
989   The available visualization contexts include
990 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
991 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
992 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
993 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
994 
995    The user can open alternative visualization contexts with
996 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
997 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
998          specified file; corresponding input uses MatLoad()
999 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1000          an X window display
1001 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1002          Currently only the sequential dense and AIJ
1003          matrix types support the Socket viewer.
1004 
1005    The user can call `PetscViewerPushFormat()` to specify the output
1006    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1007    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1008 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1009 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1010 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1011 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1012          format common among all matrix types
1013 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1014          format (which is in many cases the same as the default)
1015 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1016          size and structure (not the matrix entries)
1017 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1018          the matrix structure
1019 
1020    Options Database Keys:
1021 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1022 .  -mat_view ::ascii_info_detail - Prints more detailed info
1023 .  -mat_view - Prints matrix in ASCII format
1024 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1025 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1026 .  -display <name> - Sets display name (default is host)
1027 .  -draw_pause <sec> - Sets number of seconds to pause after display
1028 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1029 .  -viewer_socket_machine <machine> -
1030 .  -viewer_socket_port <port> -
1031 .  -mat_view binary - save matrix to file in binary format
1032 -  -viewer_binary_filename <name> -
1033 
1034    Level: beginner
1035 
1036    Notes:
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072   MatCheckPreallocated(mat, 1);
1073 
1074   PetscCall(PetscViewerGetFormat(viewer, &format));
1075   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1076   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1077 
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1080   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1081   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");
1082 
1083   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1084   if (isascii) {
1085     PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix");
1086     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1087     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1088       MatNullSpace nullsp, transnullsp;
1089 
1090       PetscCall(PetscViewerASCIIPushTab(viewer));
1091       PetscCall(MatGetSize(mat, &rows, &cols));
1092       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1093       if (rbs != 1 || cbs != 1) {
1094         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1095         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1096       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1097       if (mat->factortype) {
1098         MatSolverType solver;
1099         PetscCall(MatFactorGetSolverType(mat, &solver));
1100         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1101       }
1102       if (mat->ops->getinfo) {
1103         MatInfo info;
1104         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1105         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1106         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1107       }
1108       PetscCall(MatGetNullSpace(mat, &nullsp));
1109       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1110       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1111       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1112       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1113       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1114       PetscCall(PetscViewerASCIIPushTab(viewer));
1115       PetscCall(MatProductView(mat, viewer));
1116       PetscCall(PetscViewerASCIIPopTab(viewer));
1117     }
1118   } else if (issaws) {
1119 #if defined(PETSC_HAVE_SAWS)
1120     PetscMPIInt rank;
1121 
1122     PetscCall(PetscObjectName((PetscObject)mat));
1123     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1124     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1125 #endif
1126   } else if (isstring) {
1127     const char *type;
1128     PetscCall(MatGetType(mat, &type));
1129     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1130     PetscTryTypeMethod(mat, view, viewer);
1131   }
1132   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1133     PetscCall(PetscViewerASCIIPushTab(viewer));
1134     PetscUseTypeMethod(mat, viewnative, viewer);
1135     PetscCall(PetscViewerASCIIPopTab(viewer));
1136   } else if (mat->ops->view) {
1137     PetscCall(PetscViewerASCIIPushTab(viewer));
1138     PetscUseTypeMethod(mat, view, viewer);
1139     PetscCall(PetscViewerASCIIPopTab(viewer));
1140   }
1141   if (isascii) {
1142     PetscCall(PetscViewerGetFormat(viewer, &format));
1143     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1144   }
1145   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1146   PetscFunctionReturn(0);
1147 }
1148 
1149 #if defined(PETSC_USE_DEBUG)
1150   #include <../src/sys/totalview/tv_data_display.h>
1151 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1152 {
1153   TV_add_row("Local rows", "int", &mat->rmap->n);
1154   TV_add_row("Local columns", "int", &mat->cmap->n);
1155   TV_add_row("Global rows", "int", &mat->rmap->N);
1156   TV_add_row("Global columns", "int", &mat->cmap->N);
1157   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1158   return TV_format_OK;
1159 }
1160 #endif
1161 
1162 /*@C
1163    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1164    with `MatView()`.  The matrix format is determined from the options database.
1165    Generates a parallel MPI matrix if the communicator has more than one
1166    processor.  The default matrix type is `MATAIJ`.
1167 
1168    Collective on mat
1169 
1170    Input Parameters:
1171 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1172             or some related function before a call to `MatLoad()`
1173 -  viewer - binary/HDF5 file viewer
1174 
1175    Options Database Keys:
1176    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1177    block size
1178 .    -matload_block_size <bs> - set block size
1179 
1180    Level: beginner
1181 
1182    Notes:
1183    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1184    `Mat` before calling this routine if you wish to set it from the options database.
1185 
1186    `MatLoad()` automatically loads into the options database any options
1187    given in the file filename.info where filename is the name of the file
1188    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1189    file will be ignored if you use the -viewer_binary_skip_info option.
1190 
1191    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1192    sets the default matrix type AIJ and sets the local and global sizes.
1193    If type and/or size is already set, then the same are used.
1194 
1195    In parallel, each processor can load a subset of rows (or the
1196    entire matrix).  This routine is especially useful when a large
1197    matrix is stored on disk and only part of it is desired on each
1198    processor.  For example, a parallel solver may access only some of
1199    the rows from each processor.  The algorithm used here reads
1200    relatively small blocks of data rather than reading the entire
1201    matrix and then subsetting it.
1202 
1203    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1204    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1205    or the sequence like
1206 .vb
1207     `PetscViewer` v;
1208     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1209     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1210     `PetscViewerSetFromOptions`(v);
1211     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1212     `PetscViewerFileSetName`(v,"datafile");
1213 .ve
1214    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1215 $ -viewer_type {binary,hdf5}
1216 
1217    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1218    and src/mat/tutorials/ex10.c with the second approach.
1219 
1220    Notes about the PETSc binary format:
1221    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1222    is read onto rank 0 and then shipped to its destination rank, one after another.
1223    Multiple objects, both matrices and vectors, can be stored within the same file.
1224    Their PetscObject name is ignored; they are loaded in the order of their storage.
1225 
1226    Most users should not need to know the details of the binary storage
1227    format, since `MatLoad()` and `MatView()` completely hide these details.
1228    But for anyone who's interested, the standard binary matrix storage
1229    format is
1230 
1231 $    PetscInt    MAT_FILE_CLASSID
1232 $    PetscInt    number of rows
1233 $    PetscInt    number of columns
1234 $    PetscInt    total number of nonzeros
1235 $    PetscInt    *number nonzeros in each row
1236 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1237 $    PetscScalar *values of all nonzeros
1238 
1239    PETSc automatically does the byte swapping for
1240 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1241 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1242 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1243 and `PetscBinaryWrite()` to see how this may be done.
1244 
1245    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1246    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1247    Each processor's chunk is loaded independently by its owning rank.
1248    Multiple objects, both matrices and vectors, can be stored within the same file.
1249    They are looked up by their PetscObject name.
1250 
1251    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1252    by default the same structure and naming of the AIJ arrays and column count
1253    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1254 $    save example.mat A b -v7.3
1255    can be directly read by this routine (see Reference 1 for details).
1256    Note that depending on your MATLAB version, this format might be a default,
1257    otherwise you can set it as default in Preferences.
1258 
1259    Unless -nocompression flag is used to save the file in MATLAB,
1260    PETSc must be configured with ZLIB package.
1261 
1262    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1263 
1264    Current HDF5 (MAT-File) limitations:
1265    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1266 
1267    Corresponding `MatView()` is not yet implemented.
1268 
1269    The loaded matrix is actually a transpose of the original one in MATLAB,
1270    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1271    With this format, matrix is automatically transposed by PETSc,
1272    unless the matrix is marked as SPD or symmetric
1273    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1274 
1275    References:
1276 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1277 
1278 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1279  @*/
1280 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1281 {
1282   PetscBool flg;
1283 
1284   PetscFunctionBegin;
1285   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1286   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1287 
1288   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1289 
1290   flg = PETSC_FALSE;
1291   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1292   if (flg) {
1293     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1294     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1295   }
1296   flg = PETSC_FALSE;
1297   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1298   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1299 
1300   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1301   PetscUseTypeMethod(mat, load, viewer);
1302   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1303   PetscFunctionReturn(0);
1304 }
1305 
1306 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1307 {
1308   Mat_Redundant *redund = *redundant;
1309 
1310   PetscFunctionBegin;
1311   if (redund) {
1312     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1313       PetscCall(ISDestroy(&redund->isrow));
1314       PetscCall(ISDestroy(&redund->iscol));
1315       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1316     } else {
1317       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1318       PetscCall(PetscFree(redund->sbuf_j));
1319       PetscCall(PetscFree(redund->sbuf_a));
1320       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1321         PetscCall(PetscFree(redund->rbuf_j[i]));
1322         PetscCall(PetscFree(redund->rbuf_a[i]));
1323       }
1324       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1325     }
1326 
1327     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1328     PetscCall(PetscFree(redund));
1329   }
1330   PetscFunctionReturn(0);
1331 }
1332 
1333 /*@C
1334    MatDestroy - Frees space taken by a matrix.
1335 
1336    Collective on A
1337 
1338    Input Parameter:
1339 .  A - the matrix
1340 
1341    Level: beginner
1342 
1343    Developer Note:
1344    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1345    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1346    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1347    if changes are needed here.
1348 
1349 .seealso: `Mat`, `MatCreate()`
1350 @*/
1351 PetscErrorCode MatDestroy(Mat *A)
1352 {
1353   PetscFunctionBegin;
1354   if (!*A) PetscFunctionReturn(0);
1355   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1356   if (--((PetscObject)(*A))->refct > 0) {
1357     *A = NULL;
1358     PetscFunctionReturn(0);
1359   }
1360 
1361   /* if memory was published with SAWs then destroy it */
1362   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1363   PetscTryTypeMethod((*A), destroy);
1364 
1365   PetscCall(PetscFree((*A)->factorprefix));
1366   PetscCall(PetscFree((*A)->defaultvectype));
1367   PetscCall(PetscFree((*A)->defaultrandtype));
1368   PetscCall(PetscFree((*A)->bsizes));
1369   PetscCall(PetscFree((*A)->solvertype));
1370   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1371   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1372   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1373   PetscCall(MatProductClear(*A));
1374   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1375   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1376   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1377   PetscCall(MatDestroy(&(*A)->schur));
1378   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1379   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1380   PetscCall(PetscHeaderDestroy(A));
1381   PetscFunctionReturn(0);
1382 }
1383 
1384 /*@C
1385    MatSetValues - Inserts or adds a block of values into a matrix.
1386    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1387    MUST be called after all calls to `MatSetValues()` have been completed.
1388 
1389    Not Collective
1390 
1391    Input Parameters:
1392 +  mat - the matrix
1393 .  v - a logically two-dimensional array of values
1394 .  m, idxm - the number of rows and their global indices
1395 .  n, idxn - the number of columns and their global indices
1396 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1397 
1398    Notes:
1399    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1400       `MatSetUp()` before using this routine
1401 
1402    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1403 
1404    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1405    options cannot be mixed without intervening calls to the assembly
1406    routines.
1407 
1408    `MatSetValues()` uses 0-based row and column numbers in Fortran
1409    as well as in C.
1410 
1411    Negative indices may be passed in idxm and idxn, these rows and columns are
1412    simply ignored. This allows easily inserting element stiffness matrices
1413    with homogeneous Dirchlet boundary conditions that you don't want represented
1414    in the matrix.
1415 
1416    Efficiency Alert:
1417    The routine `MatSetValuesBlocked()` may offer much better efficiency
1418    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1419 
1420    Level: beginner
1421 
1422    Developer Note:
1423    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1424    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1425 
1426 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1427           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1428 @*/
1429 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1430 {
1431   PetscFunctionBeginHot;
1432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1433   PetscValidType(mat, 1);
1434   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1435   PetscValidIntPointer(idxm, 3);
1436   PetscValidIntPointer(idxn, 5);
1437   MatCheckPreallocated(mat, 1);
1438 
1439   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1440   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1441 
1442   if (PetscDefined(USE_DEBUG)) {
1443     PetscInt i, j;
1444 
1445     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1446     for (i = 0; i < m; i++) {
1447       for (j = 0; j < n; j++) {
1448         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1449 #if defined(PETSC_USE_COMPLEX)
1450           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]);
1451 #else
1452           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]);
1453 #endif
1454       }
1455     }
1456     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);
1457     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);
1458   }
1459 
1460   if (mat->assembled) {
1461     mat->was_assembled = PETSC_TRUE;
1462     mat->assembled     = PETSC_FALSE;
1463   }
1464   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1465   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1466   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1467   PetscFunctionReturn(0);
1468 }
1469 
1470 /*@C
1471    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1472    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1473    MUST be called after all calls to `MatSetValues()` have been completed.
1474 
1475    Not Collective
1476 
1477    Input Parameters:
1478 +  mat - the matrix
1479 .  v - a logically two-dimensional array of values
1480 .  ism - the rows to provide
1481 .  isn - the columns to provide
1482 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1483 
1484    Notes:
1485    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1486       `MatSetUp()` before using this routine
1487 
1488    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1489 
1490    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1491    options cannot be mixed without intervening calls to the assembly
1492    routines.
1493 
1494    MatSetValues() uses 0-based row and column numbers in Fortran
1495    as well as in C.
1496 
1497    Negative indices may be passed in ism and isn, these rows and columns are
1498    simply ignored. This allows easily inserting element stiffness matrices
1499    with homogeneous Dirchlet boundary conditions that you don't want represented
1500    in the matrix.
1501 
1502    Efficiency Alert:
1503    The routine `MatSetValuesBlocked()` may offer much better efficiency
1504    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1505 
1506    Level: beginner
1507 
1508    Developer Notes:
1509     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1510                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1511 
1512     This is currently not optimized for any particular `ISType`
1513 
1514 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1515           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1516 @*/
1517 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1518 {
1519   PetscInt        m, n;
1520   const PetscInt *rows, *cols;
1521 
1522   PetscFunctionBeginHot;
1523   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1524   PetscCall(ISGetIndices(ism, &rows));
1525   PetscCall(ISGetIndices(isn, &cols));
1526   PetscCall(ISGetLocalSize(ism, &m));
1527   PetscCall(ISGetLocalSize(isn, &n));
1528   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1529   PetscCall(ISRestoreIndices(ism, &rows));
1530   PetscCall(ISRestoreIndices(isn, &cols));
1531   PetscFunctionReturn(0);
1532 }
1533 
1534 /*@
1535    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1536         values into a matrix
1537 
1538    Not Collective
1539 
1540    Input Parameters:
1541 +  mat - the matrix
1542 .  row - the (block) row to set
1543 -  v - a logically two-dimensional array of values
1544 
1545    Notes:
1546    By the values, v, are column-oriented (for the block version) and sorted
1547 
1548    All the nonzeros in the row must be provided
1549 
1550    The matrix must have previously had its column indices set
1551 
1552    The row must belong to this process
1553 
1554    Level: intermediate
1555 
1556 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1557           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1558 @*/
1559 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1560 {
1561   PetscInt globalrow;
1562 
1563   PetscFunctionBegin;
1564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1565   PetscValidType(mat, 1);
1566   PetscValidScalarPointer(v, 3);
1567   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1568   PetscCall(MatSetValuesRow(mat, globalrow, v));
1569   PetscFunctionReturn(0);
1570 }
1571 
1572 /*@
1573    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1574         values into a matrix
1575 
1576    Not Collective
1577 
1578    Input Parameters:
1579 +  mat - the matrix
1580 .  row - the (block) row to set
1581 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1582 
1583    Notes:
1584    The values, v, are column-oriented for the block version.
1585 
1586    All the nonzeros in the row must be provided
1587 
1588    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1589 
1590    The row must belong to this process
1591 
1592    Level: advanced
1593 
1594 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1595           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1596 @*/
1597 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1598 {
1599   PetscFunctionBeginHot;
1600   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1601   PetscValidType(mat, 1);
1602   MatCheckPreallocated(mat, 1);
1603   PetscValidScalarPointer(v, 3);
1604   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1605   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1606   mat->insertmode = INSERT_VALUES;
1607 
1608   if (mat->assembled) {
1609     mat->was_assembled = PETSC_TRUE;
1610     mat->assembled     = PETSC_FALSE;
1611   }
1612   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1613   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1614   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1615   PetscFunctionReturn(0);
1616 }
1617 
1618 /*@
1619    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1620      Using structured grid indexing
1621 
1622    Not Collective
1623 
1624    Input Parameters:
1625 +  mat - the matrix
1626 .  m - number of rows being entered
1627 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1628 .  n - number of columns being entered
1629 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1630 .  v - a logically two-dimensional array of values
1631 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1632 
1633    Notes:
1634    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1635 
1636    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1637    options cannot be mixed without intervening calls to the assembly
1638    routines.
1639 
1640    The grid coordinates are across the entire grid, not just the local portion
1641 
1642    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1643    as well as in C.
1644 
1645    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1646 
1647    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1648    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1649 
1650    The columns and rows in the stencil passed in MUST be contained within the
1651    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1652    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1653    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1654    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1655 
1656    In Fortran idxm and idxn should be declared as
1657 $     MatStencil idxm(4,m),idxn(4,n)
1658    and the values inserted using
1659 $    idxm(MatStencil_i,1) = i
1660 $    idxm(MatStencil_j,1) = j
1661 $    idxm(MatStencil_k,1) = k
1662 $    idxm(MatStencil_c,1) = c
1663    etc
1664 
1665    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1666    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1667    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1668    `DM_BOUNDARY_PERIODIC` boundary type.
1669 
1670    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
1671    a single value per point) you can skip filling those indices.
1672 
1673    Inspired by the structured grid interface to the HYPRE package
1674    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1675 
1676    Efficiency Alert:
1677    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1678    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1679 
1680    Level: beginner
1681 
1682 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1683           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1684 @*/
1685 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1686 {
1687   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1688   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1689   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1690 
1691   PetscFunctionBegin;
1692   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1693   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1694   PetscValidType(mat, 1);
1695   PetscValidPointer(idxm, 3);
1696   PetscValidPointer(idxn, 5);
1697 
1698   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1699     jdxm = buf;
1700     jdxn = buf + m;
1701   } else {
1702     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1703     jdxm = bufm;
1704     jdxn = bufn;
1705   }
1706   for (i = 0; i < m; i++) {
1707     for (j = 0; j < 3 - sdim; j++) dxm++;
1708     tmp = *dxm++ - starts[0];
1709     for (j = 0; j < dim - 1; j++) {
1710       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1711       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1712     }
1713     if (mat->stencil.noc) dxm++;
1714     jdxm[i] = tmp;
1715   }
1716   for (i = 0; i < n; i++) {
1717     for (j = 0; j < 3 - sdim; j++) dxn++;
1718     tmp = *dxn++ - starts[0];
1719     for (j = 0; j < dim - 1; j++) {
1720       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1721       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1722     }
1723     if (mat->stencil.noc) dxn++;
1724     jdxn[i] = tmp;
1725   }
1726   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1727   PetscCall(PetscFree2(bufm, bufn));
1728   PetscFunctionReturn(0);
1729 }
1730 
1731 /*@
1732    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1733      Using structured grid indexing
1734 
1735    Not Collective
1736 
1737    Input Parameters:
1738 +  mat - the matrix
1739 .  m - number of rows being entered
1740 .  idxm - grid coordinates for matrix rows being entered
1741 .  n - number of columns being entered
1742 .  idxn - grid coordinates for matrix columns being entered
1743 .  v - a logically two-dimensional array of values
1744 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1745 
1746    Notes:
1747    By default the values, v, are row-oriented and unsorted.
1748    See `MatSetOption()` for other options.
1749 
1750    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1751    options cannot be mixed without intervening calls to the assembly
1752    routines.
1753 
1754    The grid coordinates are across the entire grid, not just the local portion
1755 
1756    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1757    as well as in C.
1758 
1759    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1760 
1761    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1762    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1763 
1764    The columns and rows in the stencil passed in MUST be contained within the
1765    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1766    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1767    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1768    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1769 
1770    In Fortran idxm and idxn should be declared as
1771 $     MatStencil idxm(4,m),idxn(4,n)
1772    and the values inserted using
1773 $    idxm(MatStencil_i,1) = i
1774 $    idxm(MatStencil_j,1) = j
1775 $    idxm(MatStencil_k,1) = k
1776    etc
1777 
1778    Negative indices may be passed in idxm and idxn, these rows and columns are
1779    simply ignored. This allows easily inserting element stiffness matrices
1780    with homogeneous Dirchlet boundary conditions that you don't want represented
1781    in the matrix.
1782 
1783    Inspired by the structured grid interface to the HYPRE package
1784    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1785 
1786    Level: beginner
1787 
1788 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1789           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1790           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1791 @*/
1792 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1793 {
1794   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1795   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1796   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1797 
1798   PetscFunctionBegin;
1799   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1800   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1801   PetscValidType(mat, 1);
1802   PetscValidPointer(idxm, 3);
1803   PetscValidPointer(idxn, 5);
1804   PetscValidScalarPointer(v, 6);
1805 
1806   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1807     jdxm = buf;
1808     jdxn = buf + m;
1809   } else {
1810     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1811     jdxm = bufm;
1812     jdxn = bufn;
1813   }
1814   for (i = 0; i < m; i++) {
1815     for (j = 0; j < 3 - sdim; j++) dxm++;
1816     tmp = *dxm++ - starts[0];
1817     for (j = 0; j < sdim - 1; j++) {
1818       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1819       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1820     }
1821     dxm++;
1822     jdxm[i] = tmp;
1823   }
1824   for (i = 0; i < n; i++) {
1825     for (j = 0; j < 3 - sdim; j++) dxn++;
1826     tmp = *dxn++ - starts[0];
1827     for (j = 0; j < sdim - 1; j++) {
1828       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1829       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1830     }
1831     dxn++;
1832     jdxn[i] = tmp;
1833   }
1834   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1835   PetscCall(PetscFree2(bufm, bufn));
1836   PetscFunctionReturn(0);
1837 }
1838 
1839 /*@
1840    MatSetStencil - Sets the grid information for setting values into a matrix via
1841         `MatSetValuesStencil()`
1842 
1843    Not Collective
1844 
1845    Input Parameters:
1846 +  mat - the matrix
1847 .  dim - dimension of the grid 1, 2, or 3
1848 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1849 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1850 -  dof - number of degrees of freedom per node
1851 
1852    Notes:
1853    Inspired by the structured grid interface to the HYPRE package
1854    (www.llnl.gov/CASC/hyper)
1855 
1856    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1857    user.
1858 
1859    Level: beginner
1860 
1861 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1862           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1863 @*/
1864 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1865 {
1866   PetscFunctionBegin;
1867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1868   PetscValidIntPointer(dims, 3);
1869   PetscValidIntPointer(starts, 4);
1870 
1871   mat->stencil.dim = dim + (dof > 1);
1872   for (PetscInt i = 0; i < dim; i++) {
1873     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1874     mat->stencil.starts[i] = starts[dim - i - 1];
1875   }
1876   mat->stencil.dims[dim]   = dof;
1877   mat->stencil.starts[dim] = 0;
1878   mat->stencil.noc         = (PetscBool)(dof == 1);
1879   PetscFunctionReturn(0);
1880 }
1881 
1882 /*@C
1883    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1884 
1885    Not Collective
1886 
1887    Input Parameters:
1888 +  mat - the matrix
1889 .  v - a logically two-dimensional array of values
1890 .  m, idxm - the number of block rows and their global block indices
1891 .  n, idxn - the number of block columns and their global block indices
1892 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1893 
1894    Notes:
1895    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1896    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1897 
1898    The m and n count the NUMBER of blocks in the row direction and column direction,
1899    NOT the total number of rows/columns; for example, if the block size is 2 and
1900    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1901    The values in idxm would be 1 2; that is the first index for each block divided by
1902    the block size.
1903 
1904    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1905    preallocating it).
1906 
1907    By default the values, v, are row-oriented, so the layout of
1908    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1909 
1910    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1911    options cannot be mixed without intervening calls to the assembly
1912    routines.
1913 
1914    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1915    as well as in C.
1916 
1917    Negative indices may be passed in idxm and idxn, these rows and columns are
1918    simply ignored. This allows easily inserting element stiffness matrices
1919    with homogeneous Dirchlet boundary conditions that you don't want represented
1920    in the matrix.
1921 
1922    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1923    internal searching must be done to determine where to place the
1924    data in the matrix storage space.  By instead inserting blocks of
1925    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1926    reduced.
1927 
1928    Example:
1929 $   Suppose m=n=2 and block size(bs) = 2 The array is
1930 $
1931 $   1  2  | 3  4
1932 $   5  6  | 7  8
1933 $   - - - | - - -
1934 $   9  10 | 11 12
1935 $   13 14 | 15 16
1936 $
1937 $   v[] should be passed in like
1938 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1939 $
1940 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1941 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1942 
1943    Level: intermediate
1944 
1945 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1946 @*/
1947 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1948 {
1949   PetscFunctionBeginHot;
1950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1951   PetscValidType(mat, 1);
1952   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1953   PetscValidIntPointer(idxm, 3);
1954   PetscValidIntPointer(idxn, 5);
1955   MatCheckPreallocated(mat, 1);
1956   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1957   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1958   if (PetscDefined(USE_DEBUG)) {
1959     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1960     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1961   }
1962   if (PetscDefined(USE_DEBUG)) {
1963     PetscInt rbs, cbs, M, N, i;
1964     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1965     PetscCall(MatGetSize(mat, &M, &N));
1966     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);
1967     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);
1968   }
1969   if (mat->assembled) {
1970     mat->was_assembled = PETSC_TRUE;
1971     mat->assembled     = PETSC_FALSE;
1972   }
1973   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1974   if (mat->ops->setvaluesblocked) {
1975     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1976   } else {
1977     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1978     PetscInt i, j, bs, cbs;
1979 
1980     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1981     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1982       iidxm = buf;
1983       iidxn = buf + m * bs;
1984     } else {
1985       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1986       iidxm = bufr;
1987       iidxn = bufc;
1988     }
1989     for (i = 0; i < m; i++) {
1990       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1991     }
1992     if (m != n || bs != cbs || idxm != idxn) {
1993       for (i = 0; i < n; i++) {
1994         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1995       }
1996     } else iidxn = iidxm;
1997     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
1998     PetscCall(PetscFree2(bufr, bufc));
1999   }
2000   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2001   PetscFunctionReturn(0);
2002 }
2003 
2004 /*@C
2005    MatGetValues - Gets a block of local values from a matrix.
2006 
2007    Not Collective; can only return values that are owned by the give process
2008 
2009    Input Parameters:
2010 +  mat - the matrix
2011 .  v - a logically two-dimensional array for storing the values
2012 .  m, idxm - the number of rows and their global indices
2013 -  n, idxn - the number of columns and their global indices
2014 
2015    Notes:
2016      The user must allocate space (m*n `PetscScalar`s) for the values, v.
2017      The values, v, are then returned in a row-oriented format,
2018      analogous to that used by default in `MatSetValues()`.
2019 
2020      `MatGetValues()` uses 0-based row and column numbers in
2021      Fortran as well as in C.
2022 
2023      `MatGetValues()` requires that the matrix has been assembled
2024      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2025      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2026      without intermediate matrix assembly.
2027 
2028      Negative row or column indices will be ignored and those locations in v[] will be
2029      left unchanged.
2030 
2031      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2032      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2033      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2034 
2035    Level: advanced
2036 
2037 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2038 @*/
2039 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2040 {
2041   PetscFunctionBegin;
2042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2043   PetscValidType(mat, 1);
2044   if (!m || !n) PetscFunctionReturn(0);
2045   PetscValidIntPointer(idxm, 3);
2046   PetscValidIntPointer(idxn, 5);
2047   PetscValidScalarPointer(v, 6);
2048   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2049   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2050   MatCheckPreallocated(mat, 1);
2051 
2052   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2053   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2054   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2055   PetscFunctionReturn(0);
2056 }
2057 
2058 /*@C
2059    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2060      defined previously by `MatSetLocalToGlobalMapping()`
2061 
2062    Not Collective
2063 
2064    Input Parameters:
2065 +  mat - the matrix
2066 .  nrow, irow - number of rows and their local indices
2067 -  ncol, icol - number of columns and their local indices
2068 
2069    Output Parameter:
2070 .  y -  a logically two-dimensional array of values
2071 
2072    Notes:
2073      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2074 
2075      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,
2076      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2077      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2078      with `MatSetLocalToGlobalMapping()`.
2079 
2080    Developer Note:
2081       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2082       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2083 
2084    Level: advanced
2085 
2086 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2087           `MatSetValuesLocal()`, `MatGetValues()`
2088 @*/
2089 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2090 {
2091   PetscFunctionBeginHot;
2092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2093   PetscValidType(mat, 1);
2094   MatCheckPreallocated(mat, 1);
2095   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2096   PetscValidIntPointer(irow, 3);
2097   PetscValidIntPointer(icol, 5);
2098   if (PetscDefined(USE_DEBUG)) {
2099     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2100     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2101   }
2102   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2103   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2104   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2105   else {
2106     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2107     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2108       irowm = buf;
2109       icolm = buf + nrow;
2110     } else {
2111       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2112       irowm = bufr;
2113       icolm = bufc;
2114     }
2115     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2116     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2117     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2118     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2119     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2120     PetscCall(PetscFree2(bufr, bufc));
2121   }
2122   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2123   PetscFunctionReturn(0);
2124 }
2125 
2126 /*@
2127   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2128   the same size. Currently, this can only be called once and creates the given matrix.
2129 
2130   Not Collective
2131 
2132   Input Parameters:
2133 + mat - the matrix
2134 . nb - the number of blocks
2135 . bs - the number of rows (and columns) in each block
2136 . rows - a concatenation of the rows for each block
2137 - v - a concatenation of logically two-dimensional arrays of values
2138 
2139   Note:
2140   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2141 
2142   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2143 
2144   Level: advanced
2145 
2146 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2147           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2148 @*/
2149 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2150 {
2151   PetscFunctionBegin;
2152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2153   PetscValidType(mat, 1);
2154   PetscValidIntPointer(rows, 4);
2155   PetscValidScalarPointer(v, 5);
2156   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2157 
2158   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2159   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2160   else {
2161     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2162   }
2163   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2164   PetscFunctionReturn(0);
2165 }
2166 
2167 /*@
2168    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2169    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2170    using a local (per-processor) numbering.
2171 
2172    Not Collective
2173 
2174    Input Parameters:
2175 +  x - the matrix
2176 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2177 -  cmapping - column mapping
2178 
2179    Level: intermediate
2180 
2181    Note:
2182    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2183 
2184 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2185 @*/
2186 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2187 {
2188   PetscFunctionBegin;
2189   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2190   PetscValidType(x, 1);
2191   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2192   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2193   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2194   else {
2195     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2196     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2197   }
2198   PetscFunctionReturn(0);
2199 }
2200 
2201 /*@
2202    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2203 
2204    Not Collective
2205 
2206    Input Parameter:
2207 .  A - the matrix
2208 
2209    Output Parameters:
2210 + rmapping - row mapping
2211 - cmapping - column mapping
2212 
2213    Level: advanced
2214 
2215 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2216 @*/
2217 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2218 {
2219   PetscFunctionBegin;
2220   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2221   PetscValidType(A, 1);
2222   if (rmapping) {
2223     PetscValidPointer(rmapping, 2);
2224     *rmapping = A->rmap->mapping;
2225   }
2226   if (cmapping) {
2227     PetscValidPointer(cmapping, 3);
2228     *cmapping = A->cmap->mapping;
2229   }
2230   PetscFunctionReturn(0);
2231 }
2232 
2233 /*@
2234    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2235 
2236    Logically Collective on A
2237 
2238    Input Parameters:
2239 +  A - the matrix
2240 . rmap - row layout
2241 - cmap - column layout
2242 
2243    Level: advanced
2244 
2245    Note:
2246    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2247 
2248 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2249 @*/
2250 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2251 {
2252   PetscFunctionBegin;
2253   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2254   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2255   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2256   PetscFunctionReturn(0);
2257 }
2258 
2259 /*@
2260    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2261 
2262    Not Collective
2263 
2264    Input Parameter:
2265 .  A - the matrix
2266 
2267    Output Parameters:
2268 + rmap - row layout
2269 - cmap - column layout
2270 
2271    Level: advanced
2272 
2273 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2274 @*/
2275 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2276 {
2277   PetscFunctionBegin;
2278   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2279   PetscValidType(A, 1);
2280   if (rmap) {
2281     PetscValidPointer(rmap, 2);
2282     *rmap = A->rmap;
2283   }
2284   if (cmap) {
2285     PetscValidPointer(cmap, 3);
2286     *cmap = A->cmap;
2287   }
2288   PetscFunctionReturn(0);
2289 }
2290 
2291 /*@C
2292    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2293    using a local numbering of the nodes.
2294 
2295    Not Collective
2296 
2297    Input Parameters:
2298 +  mat - the matrix
2299 .  nrow, irow - number of rows and their local indices
2300 .  ncol, icol - number of columns and their local indices
2301 .  y -  a logically two-dimensional array of values
2302 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2303 
2304    Notes:
2305    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2306       `MatSetUp()` before using this routine
2307 
2308    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2309 
2310    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2311    options cannot be mixed without intervening calls to the assembly
2312    routines.
2313 
2314    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2315    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2316 
2317    Level: intermediate
2318 
2319    Developer Note:
2320     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2321                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2322 
2323 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2324           `MatGetValuesLocal()`
2325 @*/
2326 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2327 {
2328   PetscFunctionBeginHot;
2329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2330   PetscValidType(mat, 1);
2331   MatCheckPreallocated(mat, 1);
2332   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2333   PetscValidIntPointer(irow, 3);
2334   PetscValidIntPointer(icol, 5);
2335   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2336   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2337   if (PetscDefined(USE_DEBUG)) {
2338     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2339     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2340   }
2341 
2342   if (mat->assembled) {
2343     mat->was_assembled = PETSC_TRUE;
2344     mat->assembled     = PETSC_FALSE;
2345   }
2346   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2347   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2348   else {
2349     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2350     const PetscInt *irowm, *icolm;
2351 
2352     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2353       bufr  = buf;
2354       bufc  = buf + nrow;
2355       irowm = bufr;
2356       icolm = bufc;
2357     } else {
2358       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2359       irowm = bufr;
2360       icolm = bufc;
2361     }
2362     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2363     else irowm = irow;
2364     if (mat->cmap->mapping) {
2365       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2366         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2367       } else icolm = irowm;
2368     } else icolm = icol;
2369     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2370     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2371   }
2372   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2373   PetscFunctionReturn(0);
2374 }
2375 
2376 /*@C
2377    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2378    using a local ordering of the nodes a block at a time.
2379 
2380    Not Collective
2381 
2382    Input Parameters:
2383 +  x - the matrix
2384 .  nrow, irow - number of rows and their local indices
2385 .  ncol, icol - number of columns and their local indices
2386 .  y -  a logically two-dimensional array of values
2387 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2388 
2389    Notes:
2390    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2391       `MatSetUp()` before using this routine
2392 
2393    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2394       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2395 
2396    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2397    options cannot be mixed without intervening calls to the assembly
2398    routines.
2399 
2400    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2401    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2402 
2403    Level: intermediate
2404 
2405    Developer Note:
2406     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2407                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2408 
2409 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2410           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2411 @*/
2412 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2413 {
2414   PetscFunctionBeginHot;
2415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2416   PetscValidType(mat, 1);
2417   MatCheckPreallocated(mat, 1);
2418   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2419   PetscValidIntPointer(irow, 3);
2420   PetscValidIntPointer(icol, 5);
2421   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2422   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2423   if (PetscDefined(USE_DEBUG)) {
2424     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2425     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);
2426   }
2427 
2428   if (mat->assembled) {
2429     mat->was_assembled = PETSC_TRUE;
2430     mat->assembled     = PETSC_FALSE;
2431   }
2432   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2433     PetscInt irbs, rbs;
2434     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2435     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2436     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2437   }
2438   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2439     PetscInt icbs, cbs;
2440     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2441     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2442     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2443   }
2444   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2445   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2446   else {
2447     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2448     const PetscInt *irowm, *icolm;
2449 
2450     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2451       bufr  = buf;
2452       bufc  = buf + nrow;
2453       irowm = bufr;
2454       icolm = bufc;
2455     } else {
2456       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2457       irowm = bufr;
2458       icolm = bufc;
2459     }
2460     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2461     else irowm = irow;
2462     if (mat->cmap->mapping) {
2463       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2464         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2465       } else icolm = irowm;
2466     } else icolm = icol;
2467     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2468     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2469   }
2470   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2471   PetscFunctionReturn(0);
2472 }
2473 
2474 /*@
2475    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2476 
2477    Collective on mat
2478 
2479    Input Parameters:
2480 +  mat - the matrix
2481 -  x   - the vector to be multiplied
2482 
2483    Output Parameters:
2484 .  y - the result
2485 
2486    Note:
2487    The vectors x and y cannot be the same.  I.e., one cannot
2488    call `MatMultDiagonalBlock`(A,y,y).
2489 
2490    Level: developer
2491 
2492 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2493 @*/
2494 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2495 {
2496   PetscFunctionBegin;
2497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2498   PetscValidType(mat, 1);
2499   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2500   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2501 
2502   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2503   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2504   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2505   MatCheckPreallocated(mat, 1);
2506 
2507   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2508   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2509   PetscFunctionReturn(0);
2510 }
2511 
2512 /* --------------------------------------------------------*/
2513 /*@
2514    MatMult - Computes the matrix-vector product, y = Ax.
2515 
2516    Neighbor-wise Collective on mat
2517 
2518    Input Parameters:
2519 +  mat - the matrix
2520 -  x   - the vector to be multiplied
2521 
2522    Output Parameters:
2523 .  y - the result
2524 
2525    Note:
2526    The vectors x and y cannot be the same.  I.e., one cannot
2527    call `MatMult`(A,y,y).
2528 
2529    Level: beginner
2530 
2531 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2532 @*/
2533 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2534 {
2535   PetscFunctionBegin;
2536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2537   PetscValidType(mat, 1);
2538   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2539   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2540   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2541   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2542   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2543   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);
2544   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);
2545   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);
2546   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);
2547   PetscCall(VecSetErrorIfLocked(y, 3));
2548   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2549   MatCheckPreallocated(mat, 1);
2550 
2551   PetscCall(VecLockReadPush(x));
2552   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2553   PetscUseTypeMethod(mat, mult, x, y);
2554   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2555   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2556   PetscCall(VecLockReadPop(x));
2557   PetscFunctionReturn(0);
2558 }
2559 
2560 /*@
2561    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2562 
2563    Neighbor-wise Collective on mat
2564 
2565    Input Parameters:
2566 +  mat - the matrix
2567 -  x   - the vector to be multiplied
2568 
2569    Output Parameters:
2570 .  y - the result
2571 
2572    Notes:
2573    The vectors x and y cannot be the same.  I.e., one cannot
2574    call `MatMultTranspose`(A,y,y).
2575 
2576    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2577    use `MatMultHermitianTranspose()`
2578 
2579    Level: beginner
2580 
2581 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2582 @*/
2583 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2584 {
2585   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2586 
2587   PetscFunctionBegin;
2588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2589   PetscValidType(mat, 1);
2590   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2591   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2592 
2593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2594   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2595   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2596   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);
2597   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);
2598   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);
2599   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);
2600   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2601   MatCheckPreallocated(mat, 1);
2602 
2603   if (!mat->ops->multtranspose) {
2604     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2605     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);
2606   } else op = mat->ops->multtranspose;
2607   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2608   PetscCall(VecLockReadPush(x));
2609   PetscCall((*op)(mat, x, y));
2610   PetscCall(VecLockReadPop(x));
2611   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2612   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2613   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2614   PetscFunctionReturn(0);
2615 }
2616 
2617 /*@
2618    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2619 
2620    Neighbor-wise Collective on mat
2621 
2622    Input Parameters:
2623 +  mat - the matrix
2624 -  x   - the vector to be multilplied
2625 
2626    Output Parameters:
2627 .  y - the result
2628 
2629    Notes:
2630    The vectors x and y cannot be the same.  I.e., one cannot
2631    call `MatMultHermitianTranspose`(A,y,y).
2632 
2633    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2634 
2635    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2636 
2637    Level: beginner
2638 
2639 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2640 @*/
2641 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2642 {
2643   PetscFunctionBegin;
2644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2645   PetscValidType(mat, 1);
2646   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2647   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2648 
2649   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2650   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2651   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2652   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);
2653   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);
2654   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);
2655   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);
2656   MatCheckPreallocated(mat, 1);
2657 
2658   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2659 #if defined(PETSC_USE_COMPLEX)
2660   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2661     PetscCall(VecLockReadPush(x));
2662     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2663     else PetscUseTypeMethod(mat, mult, x, y);
2664     PetscCall(VecLockReadPop(x));
2665   } else {
2666     Vec w;
2667     PetscCall(VecDuplicate(x, &w));
2668     PetscCall(VecCopy(x, w));
2669     PetscCall(VecConjugate(w));
2670     PetscCall(MatMultTranspose(mat, w, y));
2671     PetscCall(VecDestroy(&w));
2672     PetscCall(VecConjugate(y));
2673   }
2674   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2675 #else
2676   PetscCall(MatMultTranspose(mat, x, y));
2677 #endif
2678   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2679   PetscFunctionReturn(0);
2680 }
2681 
2682 /*@
2683     MatMultAdd -  Computes v3 = v2 + A * v1.
2684 
2685     Neighbor-wise Collective on mat
2686 
2687     Input Parameters:
2688 +   mat - the matrix
2689 -   v1, v2 - the vectors
2690 
2691     Output Parameters:
2692 .   v3 - the result
2693 
2694     Note:
2695     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2696     call `MatMultAdd`(A,v1,v2,v1).
2697 
2698     Level: beginner
2699 
2700 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2701 @*/
2702 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2703 {
2704   PetscFunctionBegin;
2705   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2706   PetscValidType(mat, 1);
2707   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2708   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2709   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2710 
2711   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2712   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2713   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);
2714   /* 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);
2715      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); */
2716   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);
2717   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);
2718   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2719   MatCheckPreallocated(mat, 1);
2720 
2721   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2722   PetscCall(VecLockReadPush(v1));
2723   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2724   PetscCall(VecLockReadPop(v1));
2725   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2726   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2727   PetscFunctionReturn(0);
2728 }
2729 
2730 /*@
2731    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2732 
2733    Neighbor-wise Collective on mat
2734 
2735    Input Parameters:
2736 +  mat - the matrix
2737 -  v1, v2 - the vectors
2738 
2739    Output Parameters:
2740 .  v3 - the result
2741 
2742    Note:
2743    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2744    call `MatMultTransposeAdd`(A,v1,v2,v1).
2745 
2746    Level: beginner
2747 
2748 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2749 @*/
2750 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2751 {
2752   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2753 
2754   PetscFunctionBegin;
2755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2756   PetscValidType(mat, 1);
2757   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2758   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2759   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2760 
2761   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2762   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2763   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);
2764   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);
2765   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);
2766   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2767   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2768   MatCheckPreallocated(mat, 1);
2769 
2770   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2771   PetscCall(VecLockReadPush(v1));
2772   PetscCall((*op)(mat, v1, v2, v3));
2773   PetscCall(VecLockReadPop(v1));
2774   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2775   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2776   PetscFunctionReturn(0);
2777 }
2778 
2779 /*@
2780    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2781 
2782    Neighbor-wise Collective on mat
2783 
2784    Input Parameters:
2785 +  mat - the matrix
2786 -  v1, v2 - the vectors
2787 
2788    Output Parameters:
2789 .  v3 - the result
2790 
2791    Note:
2792    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2793    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2794 
2795    Level: beginner
2796 
2797 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2798 @*/
2799 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2800 {
2801   PetscFunctionBegin;
2802   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2803   PetscValidType(mat, 1);
2804   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2805   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2806   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2807 
2808   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2809   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2810   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2811   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);
2812   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);
2813   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);
2814   MatCheckPreallocated(mat, 1);
2815 
2816   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2817   PetscCall(VecLockReadPush(v1));
2818   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2819   else {
2820     Vec w, z;
2821     PetscCall(VecDuplicate(v1, &w));
2822     PetscCall(VecCopy(v1, w));
2823     PetscCall(VecConjugate(w));
2824     PetscCall(VecDuplicate(v3, &z));
2825     PetscCall(MatMultTranspose(mat, w, z));
2826     PetscCall(VecDestroy(&w));
2827     PetscCall(VecConjugate(z));
2828     if (v2 != v3) {
2829       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2830     } else {
2831       PetscCall(VecAXPY(v3, 1.0, z));
2832     }
2833     PetscCall(VecDestroy(&z));
2834   }
2835   PetscCall(VecLockReadPop(v1));
2836   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2837   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2838   PetscFunctionReturn(0);
2839 }
2840 
2841 /*@C
2842    MatGetFactorType - gets the type of factorization it is
2843 
2844    Not Collective
2845 
2846    Input Parameters:
2847 .  mat - the matrix
2848 
2849    Output Parameters:
2850 .  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`
2851 
2852    Level: intermediate
2853 
2854 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2855           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2856 @*/
2857 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2858 {
2859   PetscFunctionBegin;
2860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2861   PetscValidType(mat, 1);
2862   PetscValidPointer(t, 2);
2863   *t = mat->factortype;
2864   PetscFunctionReturn(0);
2865 }
2866 
2867 /*@C
2868    MatSetFactorType - sets the type of factorization it is
2869 
2870    Logically Collective on mat
2871 
2872    Input Parameters:
2873 +  mat - the matrix
2874 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2875 
2876    Level: intermediate
2877 
2878 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2879           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2880 @*/
2881 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2882 {
2883   PetscFunctionBegin;
2884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2885   PetscValidType(mat, 1);
2886   mat->factortype = t;
2887   PetscFunctionReturn(0);
2888 }
2889 
2890 /* ------------------------------------------------------------*/
2891 /*@C
2892    MatGetInfo - Returns information about matrix storage (number of
2893    nonzeros, memory, etc.).
2894 
2895    Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2896 
2897    Input Parameter:
2898 .  mat - the matrix
2899 
2900    Output Parameters:
2901 +  flag - flag indicating the type of parameters to be returned
2902    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2903    MAT_GLOBAL_SUM - sum over all processors)
2904 -  info - matrix information context
2905 
2906    Notes:
2907    The `MatInfo` context contains a variety of matrix data, including
2908    number of nonzeros allocated and used, number of mallocs during
2909    matrix assembly, etc.  Additional information for factored matrices
2910    is provided (such as the fill ratio, number of mallocs during
2911    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2912    when using the runtime options
2913 $       -info -mat_view ::ascii_info
2914 
2915    Example for C/C++ Users:
2916    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2917    data within the MatInfo context.  For example,
2918 .vb
2919       MatInfo info;
2920       Mat     A;
2921       double  mal, nz_a, nz_u;
2922 
2923       MatGetInfo(A,MAT_LOCAL,&info);
2924       mal  = info.mallocs;
2925       nz_a = info.nz_allocated;
2926 .ve
2927 
2928    Example for Fortran Users:
2929    Fortran users should declare info as a double precision
2930    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2931    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2932    a complete list of parameter names.
2933 .vb
2934       double  precision info(MAT_INFO_SIZE)
2935       double  precision mal, nz_a
2936       Mat     A
2937       integer ierr
2938 
2939       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2940       mal = info(MAT_INFO_MALLOCS)
2941       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2942 .ve
2943 
2944     Level: intermediate
2945 
2946     Developer Note: fortran interface is not autogenerated as the f90
2947     interface definition cannot be generated correctly [due to MatInfo]
2948 
2949 .seealso: `MatInfo`, `MatStashGetInfo()`
2950 @*/
2951 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2952 {
2953   PetscFunctionBegin;
2954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2955   PetscValidType(mat, 1);
2956   PetscValidPointer(info, 3);
2957   MatCheckPreallocated(mat, 1);
2958   PetscUseTypeMethod(mat, getinfo, flag, info);
2959   PetscFunctionReturn(0);
2960 }
2961 
2962 /*
2963    This is used by external packages where it is not easy to get the info from the actual
2964    matrix factorization.
2965 */
2966 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2967 {
2968   PetscFunctionBegin;
2969   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2970   PetscFunctionReturn(0);
2971 }
2972 
2973 /* ----------------------------------------------------------*/
2974 
2975 /*@C
2976    MatLUFactor - Performs in-place LU factorization of matrix.
2977 
2978    Collective on mat
2979 
2980    Input Parameters:
2981 +  mat - the matrix
2982 .  row - row permutation
2983 .  col - column permutation
2984 -  info - options for factorization, includes
2985 $          fill - expected fill as ratio of original fill.
2986 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2987 $                   Run with the option -info to determine an optimal value to use
2988 
2989    Notes:
2990    Most users should employ the `KSP` interface for linear solvers
2991    instead of working directly with matrix algebra routines such as this.
2992    See, e.g., `KSPCreate()`.
2993 
2994    This changes the state of the matrix to a factored matrix; it cannot be used
2995    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2996 
2997    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2998    when not using `KSP`.
2999 
3000    Level: developer
3001 
3002    Developer Note:
3003    The Fortran interface is not autogenerated as the f90
3004    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3005 
3006 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3007           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3008 @*/
3009 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3010 {
3011   MatFactorInfo tinfo;
3012 
3013   PetscFunctionBegin;
3014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3015   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3016   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3017   if (info) PetscValidPointer(info, 4);
3018   PetscValidType(mat, 1);
3019   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3020   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3021   MatCheckPreallocated(mat, 1);
3022   if (!info) {
3023     PetscCall(MatFactorInfoInitialize(&tinfo));
3024     info = &tinfo;
3025   }
3026 
3027   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3028   PetscUseTypeMethod(mat, lufactor, row, col, info);
3029   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3030   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3031   PetscFunctionReturn(0);
3032 }
3033 
3034 /*@C
3035    MatILUFactor - Performs in-place ILU factorization of matrix.
3036 
3037    Collective on mat
3038 
3039    Input Parameters:
3040 +  mat - the matrix
3041 .  row - row permutation
3042 .  col - column permutation
3043 -  info - structure containing
3044 $      levels - number of levels of fill.
3045 $      expected fill - as ratio of original fill.
3046 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3047                 missing diagonal entries)
3048 
3049    Notes:
3050    Most users should employ the `KSP` interface for linear solvers
3051    instead of working directly with matrix algebra routines such as this.
3052    See, e.g., `KSPCreate()`.
3053 
3054    Probably really in-place only when level of fill is zero, otherwise allocates
3055    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3056    when not using `KSP`.
3057 
3058    Level: developer
3059 
3060    Developer Note:
3061    The Fortran interface is not autogenerated as the f90
3062    interface definition cannot be generated correctly [due to MatFactorInfo]
3063 
3064 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3065 @*/
3066 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3067 {
3068   PetscFunctionBegin;
3069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3070   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3071   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3072   PetscValidPointer(info, 4);
3073   PetscValidType(mat, 1);
3074   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3075   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3076   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3077   MatCheckPreallocated(mat, 1);
3078 
3079   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3080   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3081   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3082   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3083   PetscFunctionReturn(0);
3084 }
3085 
3086 /*@C
3087    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3088    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3089 
3090    Collective on fact
3091 
3092    Input Parameters:
3093 +  fact - the factor matrix obtained with `MatGetFactor()`
3094 .  mat - the matrix
3095 .  row, col - row and column permutations
3096 -  info - options for factorization, includes
3097 .vb
3098           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3099           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3100 .ve
3101 
3102    Notes:
3103     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3104 
3105    Most users should employ the simplified `KSP` interface for linear solvers
3106    instead of working directly with matrix algebra routines such as this.
3107    See, e.g., `KSPCreate()`.
3108 
3109    Level: developer
3110 
3111    Developer Note:
3112    The Fortran interface is not autogenerated as the f90
3113    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3114 
3115 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3116 @*/
3117 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3118 {
3119   MatFactorInfo tinfo;
3120 
3121   PetscFunctionBegin;
3122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3123   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3124   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3125   if (info) PetscValidPointer(info, 5);
3126   PetscValidType(mat, 2);
3127   PetscValidPointer(fact, 1);
3128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3129   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3130   if (!(fact)->ops->lufactorsymbolic) {
3131     MatSolverType stype;
3132     PetscCall(MatFactorGetSolverType(fact, &stype));
3133     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3134   }
3135   MatCheckPreallocated(mat, 2);
3136   if (!info) {
3137     PetscCall(MatFactorInfoInitialize(&tinfo));
3138     info = &tinfo;
3139   }
3140 
3141   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3142   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3143   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3144   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3145   PetscFunctionReturn(0);
3146 }
3147 
3148 /*@C
3149    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3150    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3151 
3152    Collective on fact
3153 
3154    Input Parameters:
3155 +  fact - the factor matrix obtained with `MatGetFactor()`
3156 .  mat - the matrix
3157 -  info - options for factorization
3158 
3159    Notes:
3160    See `MatLUFactor()` for in-place factorization.  See
3161    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3162 
3163    Most users should employ the `KSP` interface for linear solvers
3164    instead of working directly with matrix algebra routines such as this.
3165    See, e.g., `KSPCreate()`.
3166 
3167    Level: developer
3168 
3169     Developer Note:
3170     The Fortran interface is not autogenerated as the f90
3171     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3172 
3173 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3174 @*/
3175 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3176 {
3177   MatFactorInfo tinfo;
3178 
3179   PetscFunctionBegin;
3180   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3181   PetscValidType(mat, 2);
3182   PetscValidPointer(fact, 1);
3183   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3184   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3185   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,
3186              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3187 
3188   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3189   MatCheckPreallocated(mat, 2);
3190   if (!info) {
3191     PetscCall(MatFactorInfoInitialize(&tinfo));
3192     info = &tinfo;
3193   }
3194 
3195   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3196   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3197   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3198   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3199   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3200   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3201   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3202   PetscFunctionReturn(0);
3203 }
3204 
3205 /*@C
3206    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3207    symmetric matrix.
3208 
3209    Collective on mat
3210 
3211    Input Parameters:
3212 +  mat - the matrix
3213 .  perm - row and column permutations
3214 -  f - expected fill as ratio of original fill
3215 
3216    Notes:
3217    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3218    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3219 
3220    Most users should employ the `KSP` interface for linear solvers
3221    instead of working directly with matrix algebra routines such as this.
3222    See, e.g., `KSPCreate()`.
3223 
3224    Level: developer
3225 
3226    Developer Note:
3227    The Fortran interface is not autogenerated as the f90
3228    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3229 
3230 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3231           `MatGetOrdering()`
3232 @*/
3233 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3234 {
3235   MatFactorInfo tinfo;
3236 
3237   PetscFunctionBegin;
3238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3239   PetscValidType(mat, 1);
3240   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3241   if (info) PetscValidPointer(info, 3);
3242   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3243   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3244   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3245   MatCheckPreallocated(mat, 1);
3246   if (!info) {
3247     PetscCall(MatFactorInfoInitialize(&tinfo));
3248     info = &tinfo;
3249   }
3250 
3251   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3252   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3253   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3254   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3255   PetscFunctionReturn(0);
3256 }
3257 
3258 /*@C
3259    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3260    of a symmetric matrix.
3261 
3262    Collective on fact
3263 
3264    Input Parameters:
3265 +  fact - the factor matrix obtained with `MatGetFactor()`
3266 .  mat - the matrix
3267 .  perm - row and column permutations
3268 -  info - options for factorization, includes
3269 $          fill - expected fill as ratio of original fill.
3270 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3271 $                   Run with the option -info to determine an optimal value to use
3272 
3273    Notes:
3274    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3275    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3276 
3277    Most users should employ the `KSP` interface for linear solvers
3278    instead of working directly with matrix algebra routines such as this.
3279    See, e.g., `KSPCreate()`.
3280 
3281    Level: developer
3282 
3283    Developer Note:
3284    The Fortran interface is not autogenerated as the f90
3285    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3286 
3287 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3288           `MatGetOrdering()`
3289 @*/
3290 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3291 {
3292   MatFactorInfo tinfo;
3293 
3294   PetscFunctionBegin;
3295   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3296   PetscValidType(mat, 2);
3297   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3298   if (info) PetscValidPointer(info, 4);
3299   PetscValidPointer(fact, 1);
3300   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3301   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3302   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3303   if (!(fact)->ops->choleskyfactorsymbolic) {
3304     MatSolverType stype;
3305     PetscCall(MatFactorGetSolverType(fact, &stype));
3306     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3307   }
3308   MatCheckPreallocated(mat, 2);
3309   if (!info) {
3310     PetscCall(MatFactorInfoInitialize(&tinfo));
3311     info = &tinfo;
3312   }
3313 
3314   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3315   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3316   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3317   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3318   PetscFunctionReturn(0);
3319 }
3320 
3321 /*@C
3322    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3323    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3324    `MatCholeskyFactorSymbolic()`.
3325 
3326    Collective on fact
3327 
3328    Input Parameters:
3329 +  fact - the factor matrix obtained with `MatGetFactor()`
3330 .  mat - the initial matrix
3331 .  info - options for factorization
3332 -  fact - the symbolic factor of mat
3333 
3334    Note:
3335    Most users should employ the `KSP` interface for linear solvers
3336    instead of working directly with matrix algebra routines such as this.
3337    See, e.g., `KSPCreate()`.
3338 
3339    Level: developer
3340 
3341    Developer Note:
3342    The Fortran interface is not autogenerated as the f90
3343    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3344 
3345 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3346 @*/
3347 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3348 {
3349   MatFactorInfo tinfo;
3350 
3351   PetscFunctionBegin;
3352   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3353   PetscValidType(mat, 2);
3354   PetscValidPointer(fact, 1);
3355   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3356   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3357   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3358   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,
3359              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3360   MatCheckPreallocated(mat, 2);
3361   if (!info) {
3362     PetscCall(MatFactorInfoInitialize(&tinfo));
3363     info = &tinfo;
3364   }
3365 
3366   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3367   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3368   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3369   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3370   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3371   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3372   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3373   PetscFunctionReturn(0);
3374 }
3375 
3376 /*@
3377    MatQRFactor - Performs in-place QR factorization of matrix.
3378 
3379    Collective on mat
3380 
3381    Input Parameters:
3382 +  mat - the matrix
3383 .  col - column permutation
3384 -  info - options for factorization, includes
3385 $          fill - expected fill as ratio of original fill.
3386 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3387 $                   Run with the option -info to determine an optimal value to use
3388 
3389    Notes:
3390    Most users should employ the `KSP` interface for linear solvers
3391    instead of working directly with matrix algebra routines such as this.
3392    See, e.g., `KSPCreate()`.
3393 
3394    This changes the state of the matrix to a factored matrix; it cannot be used
3395    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3396 
3397    Level: developer
3398 
3399    Developer Note:
3400    The Fortran interface is not autogenerated as the f90
3401    interface definition cannot be generated correctly [due to MatFactorInfo]
3402 
3403 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3404           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3405 @*/
3406 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3407 {
3408   PetscFunctionBegin;
3409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3410   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3411   if (info) PetscValidPointer(info, 3);
3412   PetscValidType(mat, 1);
3413   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3414   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3415   MatCheckPreallocated(mat, 1);
3416   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3417   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3418   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3419   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3420   PetscFunctionReturn(0);
3421 }
3422 
3423 /*@
3424    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3425    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3426 
3427    Collective on fact
3428 
3429    Input Parameters:
3430 +  fact - the factor matrix obtained with `MatGetFactor()`
3431 .  mat - the matrix
3432 .  col - column permutation
3433 -  info - options for factorization, includes
3434 $          fill - expected fill as ratio of original fill.
3435 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3436 $                   Run with the option -info to determine an optimal value to use
3437 
3438    Most users should employ the `KSP` interface for linear solvers
3439    instead of working directly with matrix algebra routines such as this.
3440    See, e.g., `KSPCreate()`.
3441 
3442    Level: developer
3443 
3444    Developer Note:
3445    The Fortran interface is not autogenerated as the f90
3446    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3447 
3448 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3449 @*/
3450 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3451 {
3452   MatFactorInfo tinfo;
3453 
3454   PetscFunctionBegin;
3455   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3456   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3457   if (info) PetscValidPointer(info, 4);
3458   PetscValidType(mat, 2);
3459   PetscValidPointer(fact, 1);
3460   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3461   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3462   MatCheckPreallocated(mat, 2);
3463   if (!info) {
3464     PetscCall(MatFactorInfoInitialize(&tinfo));
3465     info = &tinfo;
3466   }
3467 
3468   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3469   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3470   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3471   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3472   PetscFunctionReturn(0);
3473 }
3474 
3475 /*@
3476    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3477    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3478 
3479    Collective on fact
3480 
3481    Input Parameters:
3482 +  fact - the factor matrix obtained with `MatGetFactor()`
3483 .  mat - the matrix
3484 -  info - options for factorization
3485 
3486    Notes:
3487    See `MatQRFactor()` for in-place factorization.
3488 
3489    Most users should employ the `KSP` interface for linear solvers
3490    instead of working directly with matrix algebra routines such as this.
3491    See, e.g., `KSPCreate()`.
3492 
3493    Level: developer
3494 
3495    Developer Note:
3496    The Fortran interface is not autogenerated as the f90
3497    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3498 
3499 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3500 @*/
3501 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3502 {
3503   MatFactorInfo tinfo;
3504 
3505   PetscFunctionBegin;
3506   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3507   PetscValidType(mat, 2);
3508   PetscValidPointer(fact, 1);
3509   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3510   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3511   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,
3512              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3513 
3514   MatCheckPreallocated(mat, 2);
3515   if (!info) {
3516     PetscCall(MatFactorInfoInitialize(&tinfo));
3517     info = &tinfo;
3518   }
3519 
3520   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3521   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3522   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3523   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3524   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3525   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3526   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3527   PetscFunctionReturn(0);
3528 }
3529 
3530 /* ----------------------------------------------------------------*/
3531 /*@
3532    MatSolve - Solves A x = b, given a factored matrix.
3533 
3534    Neighbor-wise Collective on mat
3535 
3536    Input Parameters:
3537 +  mat - the factored matrix
3538 -  b - the right-hand-side vector
3539 
3540    Output Parameter:
3541 .  x - the result vector
3542 
3543    Notes:
3544    The vectors b and x cannot be the same.  I.e., one cannot
3545    call `MatSolve`(A,x,x).
3546 
3547    Most users should employ the `KSP` interface for linear solvers
3548    instead of working directly with matrix algebra routines such as this.
3549    See, e.g., `KSPCreate()`.
3550 
3551    Level: developer
3552 
3553 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3554 @*/
3555 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3556 {
3557   PetscFunctionBegin;
3558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3559   PetscValidType(mat, 1);
3560   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3561   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3562   PetscCheckSameComm(mat, 1, b, 2);
3563   PetscCheckSameComm(mat, 1, x, 3);
3564   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3565   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);
3566   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);
3567   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);
3568   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3569   MatCheckPreallocated(mat, 1);
3570 
3571   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3572   if (mat->factorerrortype) {
3573     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3574     PetscCall(VecSetInf(x));
3575   } else PetscUseTypeMethod(mat, solve, b, x);
3576   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3577   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3578   PetscFunctionReturn(0);
3579 }
3580 
3581 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3582 {
3583   Vec      b, x;
3584   PetscInt N, i;
3585   PetscErrorCode (*f)(Mat, Vec, Vec);
3586   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3587 
3588   PetscFunctionBegin;
3589   if (A->factorerrortype) {
3590     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3591     PetscCall(MatSetInf(X));
3592     PetscFunctionReturn(0);
3593   }
3594   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3595   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3596   PetscCall(MatBoundToCPU(A, &Abound));
3597   if (!Abound) {
3598     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3599     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3600   }
3601   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3602   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3603   PetscCall(MatGetSize(B, NULL, &N));
3604   for (i = 0; i < N; i++) {
3605     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3606     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3607     PetscCall((*f)(A, b, x));
3608     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3609     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3610   }
3611   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3612   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3613   PetscFunctionReturn(0);
3614 }
3615 
3616 /*@
3617    MatMatSolve - Solves A X = B, given a factored matrix.
3618 
3619    Neighbor-wise Collective on A
3620 
3621    Input Parameters:
3622 +  A - the factored matrix
3623 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3624 
3625    Output Parameter:
3626 .  X - the result matrix (dense matrix)
3627 
3628    Note:
3629    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3630    otherwise, B and X cannot be the same.
3631 
3632    Level: developer
3633 
3634 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3635 @*/
3636 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3637 {
3638   PetscFunctionBegin;
3639   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3640   PetscValidType(A, 1);
3641   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3642   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3643   PetscCheckSameComm(A, 1, B, 2);
3644   PetscCheckSameComm(A, 1, X, 3);
3645   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);
3646   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);
3647   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");
3648   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3649   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3650   MatCheckPreallocated(A, 1);
3651 
3652   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3653   if (!A->ops->matsolve) {
3654     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3655     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3656   } else PetscUseTypeMethod(A, matsolve, B, X);
3657   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3658   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3659   PetscFunctionReturn(0);
3660 }
3661 
3662 /*@
3663    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3664 
3665    Neighbor-wise Collective on A
3666 
3667    Input Parameters:
3668 +  A - the factored matrix
3669 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3670 
3671    Output Parameter:
3672 .  X - the result matrix (dense matrix)
3673 
3674    Note:
3675    The matrices B and X cannot be the same.  I.e., one cannot
3676    call `MatMatSolveTranspose`(A,X,X).
3677 
3678    Level: developer
3679 
3680 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3681 @*/
3682 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3683 {
3684   PetscFunctionBegin;
3685   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3686   PetscValidType(A, 1);
3687   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3688   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3689   PetscCheckSameComm(A, 1, B, 2);
3690   PetscCheckSameComm(A, 1, X, 3);
3691   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3692   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);
3693   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);
3694   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);
3695   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");
3696   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3697   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3698   MatCheckPreallocated(A, 1);
3699 
3700   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3701   if (!A->ops->matsolvetranspose) {
3702     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3703     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3704   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3705   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3706   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3707   PetscFunctionReturn(0);
3708 }
3709 
3710 /*@
3711    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3712 
3713    Neighbor-wise Collective on A
3714 
3715    Input Parameters:
3716 +  A - the factored matrix
3717 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3718 
3719    Output Parameter:
3720 .  X - the result matrix (dense matrix)
3721 
3722    Note:
3723    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
3724    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3725 
3726    Level: developer
3727 
3728 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3729 @*/
3730 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3731 {
3732   PetscFunctionBegin;
3733   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3734   PetscValidType(A, 1);
3735   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3736   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3737   PetscCheckSameComm(A, 1, Bt, 2);
3738   PetscCheckSameComm(A, 1, X, 3);
3739 
3740   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3741   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);
3742   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);
3743   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");
3744   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3745   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3746   MatCheckPreallocated(A, 1);
3747 
3748   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3749   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3750   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3751   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3752   PetscFunctionReturn(0);
3753 }
3754 
3755 /*@
3756    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3757                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3758 
3759    Neighbor-wise Collective on mat
3760 
3761    Input Parameters:
3762 +  mat - the factored matrix
3763 -  b - the right-hand-side vector
3764 
3765    Output Parameter:
3766 .  x - the result vector
3767 
3768    Notes:
3769    `MatSolve()` should be used for most applications, as it performs
3770    a forward solve followed by a backward solve.
3771 
3772    The vectors b and x cannot be the same,  i.e., one cannot
3773    call `MatForwardSolve`(A,x,x).
3774 
3775    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3776    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3777    `MatForwardSolve()` solves U^T*D y = b, and
3778    `MatBackwardSolve()` solves U x = y.
3779    Thus they do not provide a symmetric preconditioner.
3780 
3781    Level: developer
3782 
3783 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3784 @*/
3785 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3786 {
3787   PetscFunctionBegin;
3788   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3789   PetscValidType(mat, 1);
3790   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3791   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3792   PetscCheckSameComm(mat, 1, b, 2);
3793   PetscCheckSameComm(mat, 1, x, 3);
3794   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3795   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);
3796   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);
3797   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);
3798   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3799   MatCheckPreallocated(mat, 1);
3800 
3801   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3802   PetscUseTypeMethod(mat, forwardsolve, b, x);
3803   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3804   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3805   PetscFunctionReturn(0);
3806 }
3807 
3808 /*@
3809    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3810                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3811 
3812    Neighbor-wise Collective on mat
3813 
3814    Input Parameters:
3815 +  mat - the factored matrix
3816 -  b - the right-hand-side vector
3817 
3818    Output Parameter:
3819 .  x - the result vector
3820 
3821    Notes:
3822    `MatSolve()` should be used for most applications, as it performs
3823    a forward solve followed by a backward solve.
3824 
3825    The vectors b and x cannot be the same.  I.e., one cannot
3826    call `MatBackwardSolve`(A,x,x).
3827 
3828    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3829    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3830    `MatForwardSolve()` solves U^T*D y = b, and
3831    `MatBackwardSolve()` solves U x = y.
3832    Thus they do not provide a symmetric preconditioner.
3833 
3834    Level: developer
3835 
3836 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3837 @*/
3838 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3839 {
3840   PetscFunctionBegin;
3841   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3842   PetscValidType(mat, 1);
3843   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3844   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3845   PetscCheckSameComm(mat, 1, b, 2);
3846   PetscCheckSameComm(mat, 1, x, 3);
3847   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3848   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);
3849   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);
3850   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);
3851   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3852   MatCheckPreallocated(mat, 1);
3853 
3854   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3855   PetscUseTypeMethod(mat, backwardsolve, b, x);
3856   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3857   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3858   PetscFunctionReturn(0);
3859 }
3860 
3861 /*@
3862    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3863 
3864    Neighbor-wise Collective on mat
3865 
3866    Input Parameters:
3867 +  mat - the factored matrix
3868 .  b - the right-hand-side vector
3869 -  y - the vector to be added to
3870 
3871    Output Parameter:
3872 .  x - the result vector
3873 
3874    Note:
3875    The vectors b and x cannot be the same.  I.e., one cannot
3876    call `MatSolveAdd`(A,x,y,x).
3877 
3878    Level: developer
3879 
3880 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3881 @*/
3882 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3883 {
3884   PetscScalar one = 1.0;
3885   Vec         tmp;
3886 
3887   PetscFunctionBegin;
3888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3889   PetscValidType(mat, 1);
3890   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3891   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3892   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3893   PetscCheckSameComm(mat, 1, b, 2);
3894   PetscCheckSameComm(mat, 1, y, 3);
3895   PetscCheckSameComm(mat, 1, x, 4);
3896   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3897   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);
3898   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);
3899   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);
3900   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);
3901   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);
3902   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3903   MatCheckPreallocated(mat, 1);
3904 
3905   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3906   if (mat->factorerrortype) {
3907     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3908     PetscCall(VecSetInf(x));
3909   } else if (mat->ops->solveadd) {
3910     PetscUseTypeMethod(mat, solveadd, b, y, x);
3911   } else {
3912     /* do the solve then the add manually */
3913     if (x != y) {
3914       PetscCall(MatSolve(mat, b, x));
3915       PetscCall(VecAXPY(x, one, y));
3916     } else {
3917       PetscCall(VecDuplicate(x, &tmp));
3918       PetscCall(VecCopy(x, tmp));
3919       PetscCall(MatSolve(mat, b, x));
3920       PetscCall(VecAXPY(x, one, tmp));
3921       PetscCall(VecDestroy(&tmp));
3922     }
3923   }
3924   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3925   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3926   PetscFunctionReturn(0);
3927 }
3928 
3929 /*@
3930    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3931 
3932    Neighbor-wise Collective on mat
3933 
3934    Input Parameters:
3935 +  mat - the factored matrix
3936 -  b - the right-hand-side vector
3937 
3938    Output Parameter:
3939 .  x - the result vector
3940 
3941    Notes:
3942    The vectors b and x cannot be the same.  I.e., one cannot
3943    call `MatSolveTranspose`(A,x,x).
3944 
3945    Most users should employ the `KSP` interface for linear solvers
3946    instead of working directly with matrix algebra routines such as this.
3947    See, e.g., `KSPCreate()`.
3948 
3949    Level: developer
3950 
3951 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3952 @*/
3953 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3954 {
3955   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3956 
3957   PetscFunctionBegin;
3958   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3959   PetscValidType(mat, 1);
3960   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3961   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3962   PetscCheckSameComm(mat, 1, b, 2);
3963   PetscCheckSameComm(mat, 1, x, 3);
3964   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3965   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);
3966   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);
3967   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3968   MatCheckPreallocated(mat, 1);
3969   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3970   if (mat->factorerrortype) {
3971     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3972     PetscCall(VecSetInf(x));
3973   } else {
3974     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
3975     PetscCall((*f)(mat, b, x));
3976   }
3977   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
3978   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3979   PetscFunctionReturn(0);
3980 }
3981 
3982 /*@
3983    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3984                       factored matrix.
3985 
3986    Neighbor-wise Collective on mat
3987 
3988    Input Parameters:
3989 +  mat - the factored matrix
3990 .  b - the right-hand-side vector
3991 -  y - the vector to be added to
3992 
3993    Output Parameter:
3994 .  x - the result vector
3995 
3996    Note:
3997    The vectors b and x cannot be the same.  I.e., one cannot
3998    call `MatSolveTransposeAdd`(A,x,y,x).
3999 
4000    Level: developer
4001 
4002 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4003 @*/
4004 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4005 {
4006   PetscScalar one = 1.0;
4007   Vec         tmp;
4008   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4009 
4010   PetscFunctionBegin;
4011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4012   PetscValidType(mat, 1);
4013   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4014   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4015   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4016   PetscCheckSameComm(mat, 1, b, 2);
4017   PetscCheckSameComm(mat, 1, y, 3);
4018   PetscCheckSameComm(mat, 1, x, 4);
4019   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4020   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);
4021   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);
4022   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);
4023   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);
4024   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4025   MatCheckPreallocated(mat, 1);
4026 
4027   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4028   if (mat->factorerrortype) {
4029     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4030     PetscCall(VecSetInf(x));
4031   } else if (f) {
4032     PetscCall((*f)(mat, b, y, x));
4033   } else {
4034     /* do the solve then the add manually */
4035     if (x != y) {
4036       PetscCall(MatSolveTranspose(mat, b, x));
4037       PetscCall(VecAXPY(x, one, y));
4038     } else {
4039       PetscCall(VecDuplicate(x, &tmp));
4040       PetscCall(VecCopy(x, tmp));
4041       PetscCall(MatSolveTranspose(mat, b, x));
4042       PetscCall(VecAXPY(x, one, tmp));
4043       PetscCall(VecDestroy(&tmp));
4044     }
4045   }
4046   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4047   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4048   PetscFunctionReturn(0);
4049 }
4050 /* ----------------------------------------------------------------*/
4051 
4052 /*@
4053    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4054 
4055    Neighbor-wise Collective on mat
4056 
4057    Input Parameters:
4058 +  mat - the matrix
4059 .  b - the right hand side
4060 .  omega - the relaxation factor
4061 .  flag - flag indicating the type of SOR (see below)
4062 .  shift -  diagonal shift
4063 .  its - the number of iterations
4064 -  lits - the number of local iterations
4065 
4066    Output Parameter:
4067 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4068 
4069    SOR Flags:
4070 +     `SOR_FORWARD_SWEEP` - forward SOR
4071 .     `SOR_BACKWARD_SWEEP` - backward SOR
4072 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4073 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4074 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4075 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4076 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4077 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4078          upper/lower triangular part of matrix to
4079          vector (with omega)
4080 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4081 
4082    Notes:
4083    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4084    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4085    on each processor.
4086 
4087    Application programmers will not generally use `MatSOR()` directly,
4088    but instead will employ the `KSP`/`PC` interface.
4089 
4090    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4091 
4092    Most users should employ the `KSP` interface for linear solvers
4093    instead of working directly with matrix algebra routines such as this.
4094    See, e.g., `KSPCreate()`.
4095 
4096    Vectors x and b CANNOT be the same
4097 
4098    Notes for Advanced Users:
4099    The flags are implemented as bitwise inclusive or operations.
4100    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4101    to specify a zero initial guess for SSOR.
4102 
4103    Developer Note:
4104    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4105 
4106    Level: developer
4107 
4108 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4109 @*/
4110 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4111 {
4112   PetscFunctionBegin;
4113   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4114   PetscValidType(mat, 1);
4115   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4116   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4117   PetscCheckSameComm(mat, 1, b, 2);
4118   PetscCheckSameComm(mat, 1, x, 8);
4119   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4120   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4121   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);
4122   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);
4123   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);
4124   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4125   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4126   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4127 
4128   MatCheckPreallocated(mat, 1);
4129   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4130   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4131   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4132   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4133   PetscFunctionReturn(0);
4134 }
4135 
4136 /*
4137       Default matrix copy routine.
4138 */
4139 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4140 {
4141   PetscInt           i, rstart = 0, rend = 0, nz;
4142   const PetscInt    *cwork;
4143   const PetscScalar *vwork;
4144 
4145   PetscFunctionBegin;
4146   if (B->assembled) PetscCall(MatZeroEntries(B));
4147   if (str == SAME_NONZERO_PATTERN) {
4148     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4149     for (i = rstart; i < rend; i++) {
4150       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4151       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4152       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4153     }
4154   } else {
4155     PetscCall(MatAYPX(B, 0.0, A, str));
4156   }
4157   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4158   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4159   PetscFunctionReturn(0);
4160 }
4161 
4162 /*@
4163    MatCopy - Copies a matrix to another matrix.
4164 
4165    Collective on A
4166 
4167    Input Parameters:
4168 +  A - the matrix
4169 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4170 
4171    Output Parameter:
4172 .  B - where the copy is put
4173 
4174    Notes:
4175    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4176 
4177    `MatCopy()` copies the matrix entries of a matrix to another existing
4178    matrix (after first zeroing the second matrix).  A related routine is
4179    `MatConvert()`, which first creates a new matrix and then copies the data.
4180 
4181    Level: intermediate
4182 
4183 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4184 @*/
4185 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4186 {
4187   PetscInt i;
4188 
4189   PetscFunctionBegin;
4190   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4191   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4192   PetscValidType(A, 1);
4193   PetscValidType(B, 2);
4194   PetscCheckSameComm(A, 1, B, 2);
4195   MatCheckPreallocated(B, 2);
4196   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4197   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4198   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,
4199              A->cmap->N, B->cmap->N);
4200   MatCheckPreallocated(A, 1);
4201   if (A == B) PetscFunctionReturn(0);
4202 
4203   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4204   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4205   else PetscCall(MatCopy_Basic(A, B, str));
4206 
4207   B->stencil.dim = A->stencil.dim;
4208   B->stencil.noc = A->stencil.noc;
4209   for (i = 0; i <= A->stencil.dim; i++) {
4210     B->stencil.dims[i]   = A->stencil.dims[i];
4211     B->stencil.starts[i] = A->stencil.starts[i];
4212   }
4213 
4214   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4215   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4216   PetscFunctionReturn(0);
4217 }
4218 
4219 /*@C
4220    MatConvert - Converts a matrix to another matrix, either of the same
4221    or different type.
4222 
4223    Collective on mat
4224 
4225    Input Parameters:
4226 +  mat - the matrix
4227 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4228    same type as the original matrix.
4229 -  reuse - denotes if the destination matrix is to be created or reused.
4230    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
4231    `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).
4232 
4233    Output Parameter:
4234 .  M - pointer to place new matrix
4235 
4236    Notes:
4237    `MatConvert()` first creates a new matrix and then copies the data from
4238    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4239    entries of one matrix to another already existing matrix context.
4240 
4241    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4242    the MPI communicator of the generated matrix is always the same as the communicator
4243    of the input matrix.
4244 
4245    Level: intermediate
4246 
4247 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4248 @*/
4249 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4250 {
4251   PetscBool  sametype, issame, flg;
4252   PetscBool3 issymmetric, ishermitian;
4253   char       convname[256], mtype[256];
4254   Mat        B;
4255 
4256   PetscFunctionBegin;
4257   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4258   PetscValidType(mat, 1);
4259   PetscValidPointer(M, 4);
4260   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4261   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4262   MatCheckPreallocated(mat, 1);
4263 
4264   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4265   if (flg) newtype = mtype;
4266 
4267   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4268   PetscCall(PetscStrcmp(newtype, "same", &issame));
4269   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4270   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");
4271 
4272   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4273     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4274     PetscFunctionReturn(0);
4275   }
4276 
4277   /* Cache Mat options because some converters use MatHeaderReplace  */
4278   issymmetric = mat->symmetric;
4279   ishermitian = mat->hermitian;
4280 
4281   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4282     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4283     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4284   } else {
4285     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4286     const char *prefix[3]                                 = {"seq", "mpi", ""};
4287     PetscInt    i;
4288     /*
4289        Order of precedence:
4290        0) See if newtype is a superclass of the current matrix.
4291        1) See if a specialized converter is known to the current matrix.
4292        2) See if a specialized converter is known to the desired matrix class.
4293        3) See if a good general converter is registered for the desired class
4294           (as of 6/27/03 only MATMPIADJ falls into this category).
4295        4) See if a good general converter is known for the current matrix.
4296        5) Use a really basic converter.
4297     */
4298 
4299     /* 0) See if newtype is a superclass of the current matrix.
4300           i.e mat is mpiaij and newtype is aij */
4301     for (i = 0; i < 2; i++) {
4302       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4303       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4304       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4305       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4306       if (flg) {
4307         if (reuse == MAT_INPLACE_MATRIX) {
4308           PetscCall(PetscInfo(mat, "Early return\n"));
4309           PetscFunctionReturn(0);
4310         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4311           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4312           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4313           PetscFunctionReturn(0);
4314         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4315           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4316           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4317           PetscFunctionReturn(0);
4318         }
4319       }
4320     }
4321     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4322     for (i = 0; i < 3; i++) {
4323       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4324       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4325       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4326       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4327       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4328       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4329       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4330       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4331       if (conv) goto foundconv;
4332     }
4333 
4334     /* 2)  See if a specialized converter is known to the desired matrix class. */
4335     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4336     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4337     PetscCall(MatSetType(B, newtype));
4338     for (i = 0; i < 3; i++) {
4339       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4340       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4341       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4342       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4343       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4344       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4345       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4346       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4347       if (conv) {
4348         PetscCall(MatDestroy(&B));
4349         goto foundconv;
4350       }
4351     }
4352 
4353     /* 3) See if a good general converter is registered for the desired class */
4354     conv = B->ops->convertfrom;
4355     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4356     PetscCall(MatDestroy(&B));
4357     if (conv) goto foundconv;
4358 
4359     /* 4) See if a good general converter is known for the current matrix */
4360     if (mat->ops->convert) conv = mat->ops->convert;
4361     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4362     if (conv) goto foundconv;
4363 
4364     /* 5) Use a really basic converter. */
4365     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4366     conv = MatConvert_Basic;
4367 
4368   foundconv:
4369     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4370     PetscCall((*conv)(mat, newtype, reuse, M));
4371     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4372       /* the block sizes must be same if the mappings are copied over */
4373       (*M)->rmap->bs = mat->rmap->bs;
4374       (*M)->cmap->bs = mat->cmap->bs;
4375       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4376       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4377       (*M)->rmap->mapping = mat->rmap->mapping;
4378       (*M)->cmap->mapping = mat->cmap->mapping;
4379     }
4380     (*M)->stencil.dim = mat->stencil.dim;
4381     (*M)->stencil.noc = mat->stencil.noc;
4382     for (i = 0; i <= mat->stencil.dim; i++) {
4383       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4384       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4385     }
4386     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4387   }
4388   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4389 
4390   /* Copy Mat options */
4391   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4392   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4393   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4394   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4395   PetscFunctionReturn(0);
4396 }
4397 
4398 /*@C
4399    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4400 
4401    Not Collective
4402 
4403    Input Parameter:
4404 .  mat - the matrix, must be a factored matrix
4405 
4406    Output Parameter:
4407 .   type - the string name of the package (do not free this string)
4408 
4409    Note:
4410       In Fortran you pass in a empty string and the package name will be copied into it.
4411     (Make sure the string is long enough)
4412 
4413    Level: intermediate
4414 
4415 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4416 @*/
4417 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4418 {
4419   PetscErrorCode (*conv)(Mat, MatSolverType *);
4420 
4421   PetscFunctionBegin;
4422   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4423   PetscValidType(mat, 1);
4424   PetscValidPointer(type, 2);
4425   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4426   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4427   if (conv) PetscCall((*conv)(mat, type));
4428   else *type = MATSOLVERPETSC;
4429   PetscFunctionReturn(0);
4430 }
4431 
4432 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4433 struct _MatSolverTypeForSpecifcType {
4434   MatType mtype;
4435   /* no entry for MAT_FACTOR_NONE */
4436   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4437   MatSolverTypeForSpecifcType next;
4438 };
4439 
4440 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4441 struct _MatSolverTypeHolder {
4442   char                       *name;
4443   MatSolverTypeForSpecifcType handlers;
4444   MatSolverTypeHolder         next;
4445 };
4446 
4447 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4448 
4449 /*@C
4450    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4451 
4452    Input Parameters:
4453 +    package - name of the package, for example petsc or superlu
4454 .    mtype - the matrix type that works with this package
4455 .    ftype - the type of factorization supported by the package
4456 -    createfactor - routine that will create the factored matrix ready to be used
4457 
4458     Level: developer
4459 
4460 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4461 @*/
4462 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4463 {
4464   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4465   PetscBool                   flg;
4466   MatSolverTypeForSpecifcType inext, iprev = NULL;
4467 
4468   PetscFunctionBegin;
4469   PetscCall(MatInitializePackage());
4470   if (!next) {
4471     PetscCall(PetscNew(&MatSolverTypeHolders));
4472     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4473     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4474     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4475     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4476     PetscFunctionReturn(0);
4477   }
4478   while (next) {
4479     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4480     if (flg) {
4481       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4482       inext = next->handlers;
4483       while (inext) {
4484         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4485         if (flg) {
4486           inext->createfactor[(int)ftype - 1] = createfactor;
4487           PetscFunctionReturn(0);
4488         }
4489         iprev = inext;
4490         inext = inext->next;
4491       }
4492       PetscCall(PetscNew(&iprev->next));
4493       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4494       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4495       PetscFunctionReturn(0);
4496     }
4497     prev = next;
4498     next = next->next;
4499   }
4500   PetscCall(PetscNew(&prev->next));
4501   PetscCall(PetscStrallocpy(package, &prev->next->name));
4502   PetscCall(PetscNew(&prev->next->handlers));
4503   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4504   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4505   PetscFunctionReturn(0);
4506 }
4507 
4508 /*@C
4509    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4510 
4511    Input Parameters:
4512 +    type - name of the package, for example petsc or superlu
4513 .    ftype - the type of factorization supported by the type
4514 -    mtype - the matrix type that works with this type
4515 
4516    Output Parameters:
4517 +   foundtype - `PETSC_TRUE` if the type was registered
4518 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4519 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4520 
4521     Level: developer
4522 
4523 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4524 @*/
4525 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4526 {
4527   MatSolverTypeHolder         next = MatSolverTypeHolders;
4528   PetscBool                   flg;
4529   MatSolverTypeForSpecifcType inext;
4530 
4531   PetscFunctionBegin;
4532   if (foundtype) *foundtype = PETSC_FALSE;
4533   if (foundmtype) *foundmtype = PETSC_FALSE;
4534   if (createfactor) *createfactor = NULL;
4535 
4536   if (type) {
4537     while (next) {
4538       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4539       if (flg) {
4540         if (foundtype) *foundtype = PETSC_TRUE;
4541         inext = next->handlers;
4542         while (inext) {
4543           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4544           if (flg) {
4545             if (foundmtype) *foundmtype = PETSC_TRUE;
4546             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4547             PetscFunctionReturn(0);
4548           }
4549           inext = inext->next;
4550         }
4551       }
4552       next = next->next;
4553     }
4554   } else {
4555     while (next) {
4556       inext = next->handlers;
4557       while (inext) {
4558         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4559         if (flg && inext->createfactor[(int)ftype - 1]) {
4560           if (foundtype) *foundtype = PETSC_TRUE;
4561           if (foundmtype) *foundmtype = PETSC_TRUE;
4562           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4563           PetscFunctionReturn(0);
4564         }
4565         inext = inext->next;
4566       }
4567       next = next->next;
4568     }
4569     /* try with base classes inext->mtype */
4570     next = MatSolverTypeHolders;
4571     while (next) {
4572       inext = next->handlers;
4573       while (inext) {
4574         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4575         if (flg && inext->createfactor[(int)ftype - 1]) {
4576           if (foundtype) *foundtype = PETSC_TRUE;
4577           if (foundmtype) *foundmtype = PETSC_TRUE;
4578           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4579           PetscFunctionReturn(0);
4580         }
4581         inext = inext->next;
4582       }
4583       next = next->next;
4584     }
4585   }
4586   PetscFunctionReturn(0);
4587 }
4588 
4589 PetscErrorCode MatSolverTypeDestroy(void)
4590 {
4591   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4592   MatSolverTypeForSpecifcType inext, iprev;
4593 
4594   PetscFunctionBegin;
4595   while (next) {
4596     PetscCall(PetscFree(next->name));
4597     inext = next->handlers;
4598     while (inext) {
4599       PetscCall(PetscFree(inext->mtype));
4600       iprev = inext;
4601       inext = inext->next;
4602       PetscCall(PetscFree(iprev));
4603     }
4604     prev = next;
4605     next = next->next;
4606     PetscCall(PetscFree(prev));
4607   }
4608   MatSolverTypeHolders = NULL;
4609   PetscFunctionReturn(0);
4610 }
4611 
4612 /*@C
4613    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4614 
4615    Logically Collective on mat
4616 
4617    Input Parameters:
4618 .  mat - the matrix
4619 
4620    Output Parameters:
4621 .  flg - `PETSC_TRUE` if uses the ordering
4622 
4623    Note:
4624    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4625    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4626 
4627    Level: developer
4628 
4629 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4630 @*/
4631 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4632 {
4633   PetscFunctionBegin;
4634   *flg = mat->canuseordering;
4635   PetscFunctionReturn(0);
4636 }
4637 
4638 /*@C
4639    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4640 
4641    Logically Collective on mat
4642 
4643    Input Parameters:
4644 .  mat - the matrix obtained with `MatGetFactor()`
4645 
4646    Output Parameters:
4647 .  otype - the preferred type
4648 
4649    Level: developer
4650 
4651 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4652 @*/
4653 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4654 {
4655   PetscFunctionBegin;
4656   *otype = mat->preferredordering[ftype];
4657   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4658   PetscFunctionReturn(0);
4659 }
4660 
4661 /*@C
4662    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4663 
4664    Collective on mat
4665 
4666    Input Parameters:
4667 +  mat - the matrix
4668 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4669 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4670 
4671    Output Parameters:
4672 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4673 
4674    Options Database Key:
4675 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4676                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4677 
4678    Notes:
4679      Users usually access the factorization solvers via `KSP`
4680 
4681       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4682      such as pastix, superlu, mumps etc.
4683 
4684       PETSc must have been ./configure to use the external solver, using the option --download-package
4685 
4686       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4687       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4688       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4689 
4690    Developer Note:
4691       This should actually be called `MatCreateFactor()` since it creates a new factor object
4692 
4693    Level: intermediate
4694 
4695 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4696           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4697 @*/
4698 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4699 {
4700   PetscBool foundtype, foundmtype;
4701   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4702 
4703   PetscFunctionBegin;
4704   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4705   PetscValidType(mat, 1);
4706 
4707   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4708   MatCheckPreallocated(mat, 1);
4709 
4710   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4711   if (!foundtype) {
4712     if (type) {
4713       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],
4714               ((PetscObject)mat)->type_name, type);
4715     } else {
4716       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);
4717     }
4718   }
4719   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4720   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);
4721 
4722   PetscCall((*conv)(mat, ftype, f));
4723   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4724   PetscFunctionReturn(0);
4725 }
4726 
4727 /*@C
4728    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4729 
4730    Not Collective
4731 
4732    Input Parameters:
4733 +  mat - the matrix
4734 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4735 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4736 
4737    Output Parameter:
4738 .    flg - PETSC_TRUE if the factorization is available
4739 
4740    Notes:
4741       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4742      such as pastix, superlu, mumps etc.
4743 
4744       PETSc must have been ./configure to use the external solver, using the option --download-package
4745 
4746    Developer Note:
4747       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4748 
4749    Level: intermediate
4750 
4751 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4752           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4753 @*/
4754 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4755 {
4756   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4757 
4758   PetscFunctionBegin;
4759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4760   PetscValidType(mat, 1);
4761   PetscValidBoolPointer(flg, 4);
4762 
4763   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4764   MatCheckPreallocated(mat, 1);
4765 
4766   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4767   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4768   PetscFunctionReturn(0);
4769 }
4770 
4771 /*@
4772    MatDuplicate - Duplicates a matrix including the non-zero structure.
4773 
4774    Collective on mat
4775 
4776    Input Parameters:
4777 +  mat - the matrix
4778 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4779         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4780 
4781    Output Parameter:
4782 .  M - pointer to place new matrix
4783 
4784    Level: intermediate
4785 
4786    Notes:
4787     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4788 
4789     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.
4790 
4791     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
4792     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4793     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4794 
4795 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4796 @*/
4797 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4798 {
4799   Mat         B;
4800   VecType     vtype;
4801   PetscInt    i;
4802   PetscObject dm;
4803   void (*viewf)(void);
4804 
4805   PetscFunctionBegin;
4806   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4807   PetscValidType(mat, 1);
4808   PetscValidPointer(M, 3);
4809   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4810   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4811   MatCheckPreallocated(mat, 1);
4812 
4813   *M = NULL;
4814   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4815   PetscUseTypeMethod(mat, duplicate, op, M);
4816   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4817   B = *M;
4818 
4819   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4820   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4821   PetscCall(MatGetVecType(mat, &vtype));
4822   PetscCall(MatSetVecType(B, vtype));
4823 
4824   B->stencil.dim = mat->stencil.dim;
4825   B->stencil.noc = mat->stencil.noc;
4826   for (i = 0; i <= mat->stencil.dim; i++) {
4827     B->stencil.dims[i]   = mat->stencil.dims[i];
4828     B->stencil.starts[i] = mat->stencil.starts[i];
4829   }
4830 
4831   B->nooffproczerorows = mat->nooffproczerorows;
4832   B->nooffprocentries  = mat->nooffprocentries;
4833 
4834   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4835   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4836   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4837   PetscFunctionReturn(0);
4838 }
4839 
4840 /*@
4841    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4842 
4843    Logically Collective on mat
4844 
4845    Input Parameters:
4846 +  mat - the matrix
4847 -  v - the vector for storing the diagonal
4848 
4849    Output Parameter:
4850 .  v - the diagonal of the matrix
4851 
4852    Level: intermediate
4853 
4854    Note:
4855    Currently only correct in parallel for square matrices.
4856 
4857 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4858 @*/
4859 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4860 {
4861   PetscFunctionBegin;
4862   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4863   PetscValidType(mat, 1);
4864   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4865   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4866   MatCheckPreallocated(mat, 1);
4867 
4868   PetscUseTypeMethod(mat, getdiagonal, v);
4869   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4870   PetscFunctionReturn(0);
4871 }
4872 
4873 /*@C
4874    MatGetRowMin - Gets the minimum value (of the real part) of each
4875         row of the matrix
4876 
4877    Logically Collective on mat
4878 
4879    Input Parameter:
4880 .  mat - the matrix
4881 
4882    Output Parameters:
4883 +  v - the vector for storing the maximums
4884 -  idx - the indices of the column found for each row (optional)
4885 
4886    Level: intermediate
4887 
4888    Note:
4889     The result of this call are the same as if one converted the matrix to dense format
4890       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4891 
4892     This code is only implemented for a couple of matrix formats.
4893 
4894 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4895           `MatGetRowMax()`
4896 @*/
4897 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4898 {
4899   PetscFunctionBegin;
4900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4901   PetscValidType(mat, 1);
4902   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4903   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4904 
4905   if (!mat->cmap->N) {
4906     PetscCall(VecSet(v, PETSC_MAX_REAL));
4907     if (idx) {
4908       PetscInt i, m = mat->rmap->n;
4909       for (i = 0; i < m; i++) idx[i] = -1;
4910     }
4911   } else {
4912     MatCheckPreallocated(mat, 1);
4913   }
4914   PetscUseTypeMethod(mat, getrowmin, v, idx);
4915   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4916   PetscFunctionReturn(0);
4917 }
4918 
4919 /*@C
4920    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4921         row of the matrix
4922 
4923    Logically Collective on mat
4924 
4925    Input Parameter:
4926 .  mat - the matrix
4927 
4928    Output Parameters:
4929 +  v - the vector for storing the minimums
4930 -  idx - the indices of the column found for each row (or NULL if not needed)
4931 
4932    Level: intermediate
4933 
4934    Notes:
4935     if a row is completely empty or has only 0.0 values then the idx[] value for that
4936     row is 0 (the first column).
4937 
4938     This code is only implemented for a couple of matrix formats.
4939 
4940 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4941 @*/
4942 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4943 {
4944   PetscFunctionBegin;
4945   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4946   PetscValidType(mat, 1);
4947   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4948   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4949   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4950 
4951   if (!mat->cmap->N) {
4952     PetscCall(VecSet(v, 0.0));
4953     if (idx) {
4954       PetscInt i, m = mat->rmap->n;
4955       for (i = 0; i < m; i++) idx[i] = -1;
4956     }
4957   } else {
4958     MatCheckPreallocated(mat, 1);
4959     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4960     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4961   }
4962   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4963   PetscFunctionReturn(0);
4964 }
4965 
4966 /*@C
4967    MatGetRowMax - Gets the maximum value (of the real part) of each
4968         row of the matrix
4969 
4970    Logically Collective on mat
4971 
4972    Input Parameter:
4973 .  mat - the matrix
4974 
4975    Output Parameters:
4976 +  v - the vector for storing the maximums
4977 -  idx - the indices of the column found for each row (optional)
4978 
4979    Level: intermediate
4980 
4981    Notes:
4982     The result of this call are the same as if one converted the matrix to dense format
4983       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4984 
4985     This code is only implemented for a couple of matrix formats.
4986 
4987 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4988 @*/
4989 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
4990 {
4991   PetscFunctionBegin;
4992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4993   PetscValidType(mat, 1);
4994   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4995   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4996 
4997   if (!mat->cmap->N) {
4998     PetscCall(VecSet(v, PETSC_MIN_REAL));
4999     if (idx) {
5000       PetscInt i, m = mat->rmap->n;
5001       for (i = 0; i < m; i++) idx[i] = -1;
5002     }
5003   } else {
5004     MatCheckPreallocated(mat, 1);
5005     PetscUseTypeMethod(mat, getrowmax, v, idx);
5006   }
5007   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5008   PetscFunctionReturn(0);
5009 }
5010 
5011 /*@C
5012    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5013         row of the matrix
5014 
5015    Logically Collective on mat
5016 
5017    Input Parameter:
5018 .  mat - the matrix
5019 
5020    Output Parameters:
5021 +  v - the vector for storing the maximums
5022 -  idx - the indices of the column found for each row (or NULL if not needed)
5023 
5024    Level: intermediate
5025 
5026    Notes:
5027     if a row is completely empty or has only 0.0 values then the idx[] value for that
5028     row is 0 (the first column).
5029 
5030     This code is only implemented for a couple of matrix formats.
5031 
5032 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5033 @*/
5034 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5035 {
5036   PetscFunctionBegin;
5037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5038   PetscValidType(mat, 1);
5039   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5041 
5042   if (!mat->cmap->N) {
5043     PetscCall(VecSet(v, 0.0));
5044     if (idx) {
5045       PetscInt i, m = mat->rmap->n;
5046       for (i = 0; i < m; i++) idx[i] = -1;
5047     }
5048   } else {
5049     MatCheckPreallocated(mat, 1);
5050     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5051     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5052   }
5053   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5054   PetscFunctionReturn(0);
5055 }
5056 
5057 /*@
5058    MatGetRowSum - Gets the sum of each row of the matrix
5059 
5060    Logically or Neighborhood Collective on mat
5061 
5062    Input Parameters:
5063 .  mat - the matrix
5064 
5065    Output Parameter:
5066 .  v - the vector for storing the sum of rows
5067 
5068    Level: intermediate
5069 
5070    Notes:
5071     This code is slow since it is not currently specialized for different formats
5072 
5073 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5074 @*/
5075 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5076 {
5077   Vec ones;
5078 
5079   PetscFunctionBegin;
5080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5081   PetscValidType(mat, 1);
5082   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5083   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5084   MatCheckPreallocated(mat, 1);
5085   PetscCall(MatCreateVecs(mat, &ones, NULL));
5086   PetscCall(VecSet(ones, 1.));
5087   PetscCall(MatMult(mat, ones, v));
5088   PetscCall(VecDestroy(&ones));
5089   PetscFunctionReturn(0);
5090 }
5091 
5092 /*@
5093    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5094    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5095 
5096    Collective on mat
5097 
5098    Input Parameter:
5099 .  mat - the matrix to provide the transpose
5100 
5101    Output Parameter:
5102 .  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
5103 
5104    Level: advanced
5105 
5106    Note:
5107    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
5108    routine allows bypassing that call.
5109 
5110 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5111 @*/
5112 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5113 {
5114   PetscContainer  rB = NULL;
5115   MatParentState *rb = NULL;
5116 
5117   PetscFunctionBegin;
5118   PetscCall(PetscNew(&rb));
5119   rb->id    = ((PetscObject)mat)->id;
5120   rb->state = 0;
5121   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5122   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5123   PetscCall(PetscContainerSetPointer(rB, rb));
5124   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5125   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5126   PetscCall(PetscObjectDereference((PetscObject)rB));
5127   PetscFunctionReturn(0);
5128 }
5129 
5130 /*@
5131    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5132 
5133    Collective on mat
5134 
5135    Input Parameters:
5136 +  mat - the matrix to transpose
5137 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5138 
5139    Output Parameter:
5140 .  B - the transpose
5141 
5142    Notes:
5143      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5144 
5145      `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
5146      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5147 
5148      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.
5149 
5150      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5151 
5152      If mat is unchanged from the last call this function returns immediately without recomputing the result
5153 
5154      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5155 
5156    Level: intermediate
5157 
5158 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5159           `MatTransposeSymbolic()`
5160 @*/
5161 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5162 {
5163   PetscContainer  rB = NULL;
5164   MatParentState *rb = NULL;
5165 
5166   PetscFunctionBegin;
5167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5168   PetscValidType(mat, 1);
5169   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5170   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5171   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5172   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5173   MatCheckPreallocated(mat, 1);
5174   if (reuse == MAT_REUSE_MATRIX) {
5175     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5176     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5177     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5178     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5179     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5180   }
5181 
5182   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5183   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5184     PetscUseTypeMethod(mat, transpose, reuse, B);
5185     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5186   }
5187   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5188 
5189   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5190   if (reuse != MAT_INPLACE_MATRIX) {
5191     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5192     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5193     rb->state        = ((PetscObject)mat)->state;
5194     rb->nonzerostate = mat->nonzerostate;
5195   }
5196   PetscFunctionReturn(0);
5197 }
5198 
5199 /*@
5200    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5201 
5202    Collective on A
5203 
5204    Input Parameters:
5205 .  A - the matrix to transpose
5206 
5207    Output Parameter:
5208 .  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
5209       numerical portion.
5210 
5211    Level: intermediate
5212 
5213    Note:
5214    This is not supported for many matrix types, use `MatTranspose()` in those cases
5215 
5216 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5217 @*/
5218 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5219 {
5220   PetscFunctionBegin;
5221   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5222   PetscValidType(A, 1);
5223   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5224   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5225   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5226   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5227   PetscCall((*A->ops->transposesymbolic)(A, B));
5228   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5229 
5230   PetscCall(MatTransposeSetPrecursor(A, *B));
5231   PetscFunctionReturn(0);
5232 }
5233 
5234 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5235 {
5236   PetscContainer  rB;
5237   MatParentState *rb;
5238 
5239   PetscFunctionBegin;
5240   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5241   PetscValidType(A, 1);
5242   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5243   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5244   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5245   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5246   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5247   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5248   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5249   PetscFunctionReturn(0);
5250 }
5251 
5252 /*@
5253    MatIsTranspose - Test whether a matrix is another one's transpose,
5254         or its own, in which case it tests symmetry.
5255 
5256    Collective on A
5257 
5258    Input Parameters:
5259 +  A - the matrix to test
5260 -  B - the matrix to test against, this can equal the first parameter
5261 
5262    Output Parameters:
5263 .  flg - the result
5264 
5265    Notes:
5266    Only available for `MATAIJ` matrices.
5267 
5268    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5269    test involves parallel copies of the block-offdiagonal parts of the matrix.
5270 
5271    Level: intermediate
5272 
5273 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5274 @*/
5275 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5276 {
5277   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5278 
5279   PetscFunctionBegin;
5280   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5281   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5282   PetscValidBoolPointer(flg, 4);
5283   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5284   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5285   *flg = PETSC_FALSE;
5286   if (f && g) {
5287     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5288     PetscCall((*f)(A, B, tol, flg));
5289   } else {
5290     MatType mattype;
5291 
5292     PetscCall(MatGetType(f ? B : A, &mattype));
5293     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5294   }
5295   PetscFunctionReturn(0);
5296 }
5297 
5298 /*@
5299    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5300 
5301    Collective on mat
5302 
5303    Input Parameters:
5304 +  mat - the matrix to transpose and complex conjugate
5305 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5306 
5307    Output Parameter:
5308 .  B - the Hermitian transpose
5309 
5310    Level: intermediate
5311 
5312 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5313 @*/
5314 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5315 {
5316   PetscFunctionBegin;
5317   PetscCall(MatTranspose(mat, reuse, B));
5318 #if defined(PETSC_USE_COMPLEX)
5319   PetscCall(MatConjugate(*B));
5320 #endif
5321   PetscFunctionReturn(0);
5322 }
5323 
5324 /*@
5325    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5326 
5327    Collective on A
5328 
5329    Input Parameters:
5330 +  A - the matrix to test
5331 -  B - the matrix to test against, this can equal the first parameter
5332 
5333    Output Parameters:
5334 .  flg - the result
5335 
5336    Notes:
5337    Only available for `MATAIJ` matrices.
5338 
5339    The sequential algorithm
5340    has a running time of the order of the number of nonzeros; the parallel
5341    test involves parallel copies of the block-offdiagonal parts of the matrix.
5342 
5343    Level: intermediate
5344 
5345 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5346 @*/
5347 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5348 {
5349   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5350 
5351   PetscFunctionBegin;
5352   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5353   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5354   PetscValidBoolPointer(flg, 4);
5355   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5356   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5357   if (f && g) {
5358     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5359     PetscCall((*f)(A, B, tol, flg));
5360   }
5361   PetscFunctionReturn(0);
5362 }
5363 
5364 /*@
5365    MatPermute - Creates a new matrix with rows and columns permuted from the
5366    original.
5367 
5368    Collective on mat
5369 
5370    Input Parameters:
5371 +  mat - the matrix to permute
5372 .  row - row permutation, each processor supplies only the permutation for its rows
5373 -  col - column permutation, each processor supplies only the permutation for its columns
5374 
5375    Output Parameters:
5376 .  B - the permuted matrix
5377 
5378    Level: advanced
5379 
5380    Note:
5381    The index sets map from row/col of permuted matrix to row/col of original matrix.
5382    The index sets should be on the same communicator as mat and have the same local sizes.
5383 
5384    Developer Note:
5385      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5386      exploit the fact that row and col are permutations, consider implementing the
5387      more general `MatCreateSubMatrix()` instead.
5388 
5389 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5390 @*/
5391 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5392 {
5393   PetscFunctionBegin;
5394   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5395   PetscValidType(mat, 1);
5396   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5397   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5398   PetscValidPointer(B, 4);
5399   PetscCheckSameComm(mat, 1, row, 2);
5400   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5401   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5402   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5403   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5404   MatCheckPreallocated(mat, 1);
5405 
5406   if (mat->ops->permute) {
5407     PetscUseTypeMethod(mat, permute, row, col, B);
5408     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5409   } else {
5410     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5411   }
5412   PetscFunctionReturn(0);
5413 }
5414 
5415 /*@
5416    MatEqual - Compares two matrices.
5417 
5418    Collective on A
5419 
5420    Input Parameters:
5421 +  A - the first matrix
5422 -  B - the second matrix
5423 
5424    Output Parameter:
5425 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5426 
5427    Level: intermediate
5428 
5429 .seealso: `Mat`
5430 @*/
5431 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5432 {
5433   PetscFunctionBegin;
5434   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5435   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5436   PetscValidType(A, 1);
5437   PetscValidType(B, 2);
5438   PetscValidBoolPointer(flg, 3);
5439   PetscCheckSameComm(A, 1, B, 2);
5440   MatCheckPreallocated(A, 1);
5441   MatCheckPreallocated(B, 2);
5442   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5443   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5444   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,
5445              B->cmap->N);
5446   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5447     PetscUseTypeMethod(A, equal, B, flg);
5448   } else {
5449     PetscCall(MatMultEqual(A, B, 10, flg));
5450   }
5451   PetscFunctionReturn(0);
5452 }
5453 
5454 /*@
5455    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5456    matrices that are stored as vectors.  Either of the two scaling
5457    matrices can be NULL.
5458 
5459    Collective on mat
5460 
5461    Input Parameters:
5462 +  mat - the matrix to be scaled
5463 .  l - the left scaling vector (or NULL)
5464 -  r - the right scaling vector (or NULL)
5465 
5466    Note:
5467    `MatDiagonalScale()` computes A = LAR, where
5468    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5469    The L scales the rows of the matrix, the R scales the columns of the matrix.
5470 
5471    Level: intermediate
5472 
5473 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5474 @*/
5475 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5476 {
5477   PetscFunctionBegin;
5478   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5479   PetscValidType(mat, 1);
5480   if (l) {
5481     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5482     PetscCheckSameComm(mat, 1, l, 2);
5483   }
5484   if (r) {
5485     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5486     PetscCheckSameComm(mat, 1, r, 3);
5487   }
5488   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5489   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5490   MatCheckPreallocated(mat, 1);
5491   if (!l && !r) PetscFunctionReturn(0);
5492 
5493   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5494   PetscUseTypeMethod(mat, diagonalscale, l, r);
5495   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5496   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5497   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5498   PetscFunctionReturn(0);
5499 }
5500 
5501 /*@
5502     MatScale - Scales all elements of a matrix by a given number.
5503 
5504     Logically Collective on mat
5505 
5506     Input Parameters:
5507 +   mat - the matrix to be scaled
5508 -   a  - the scaling value
5509 
5510     Output Parameter:
5511 .   mat - the scaled matrix
5512 
5513     Level: intermediate
5514 
5515 .seealso: `Mat`, `MatDiagonalScale()`
5516 @*/
5517 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5518 {
5519   PetscFunctionBegin;
5520   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5521   PetscValidType(mat, 1);
5522   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5523   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5524   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5525   PetscValidLogicalCollectiveScalar(mat, a, 2);
5526   MatCheckPreallocated(mat, 1);
5527 
5528   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5529   if (a != (PetscScalar)1.0) {
5530     PetscUseTypeMethod(mat, scale, a);
5531     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5532   }
5533   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5534   PetscFunctionReturn(0);
5535 }
5536 
5537 /*@
5538    MatNorm - Calculates various norms of a matrix.
5539 
5540    Collective on mat
5541 
5542    Input Parameters:
5543 +  mat - the matrix
5544 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5545 
5546    Output Parameter:
5547 .  nrm - the resulting norm
5548 
5549    Level: intermediate
5550 
5551 .seealso: `Mat`
5552 @*/
5553 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5554 {
5555   PetscFunctionBegin;
5556   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5557   PetscValidType(mat, 1);
5558   PetscValidRealPointer(nrm, 3);
5559 
5560   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5561   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5562   MatCheckPreallocated(mat, 1);
5563 
5564   PetscUseTypeMethod(mat, norm, type, nrm);
5565   PetscFunctionReturn(0);
5566 }
5567 
5568 /*
5569      This variable is used to prevent counting of MatAssemblyBegin() that
5570    are called from within a MatAssemblyEnd().
5571 */
5572 static PetscInt MatAssemblyEnd_InUse = 0;
5573 /*@
5574    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5575    be called after completing all calls to `MatSetValues()`.
5576 
5577    Collective on mat
5578 
5579    Input Parameters:
5580 +  mat - the matrix
5581 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5582 
5583    Notes:
5584    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5585    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5586 
5587    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5588    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5589    using the matrix.
5590 
5591    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5592    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
5593    a global collective operation requring all processes that share the matrix.
5594 
5595    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5596    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5597    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5598 
5599    Level: beginner
5600 
5601 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5602 @*/
5603 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5604 {
5605   PetscFunctionBegin;
5606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5607   PetscValidType(mat, 1);
5608   MatCheckPreallocated(mat, 1);
5609   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5610   if (mat->assembled) {
5611     mat->was_assembled = PETSC_TRUE;
5612     mat->assembled     = PETSC_FALSE;
5613   }
5614 
5615   if (!MatAssemblyEnd_InUse) {
5616     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5617     PetscTryTypeMethod(mat, assemblybegin, type);
5618     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5619   } else PetscTryTypeMethod(mat, assemblybegin, type);
5620   PetscFunctionReturn(0);
5621 }
5622 
5623 /*@
5624    MatAssembled - Indicates if a matrix has been assembled and is ready for
5625      use; for example, in matrix-vector product.
5626 
5627    Not Collective
5628 
5629    Input Parameter:
5630 .  mat - the matrix
5631 
5632    Output Parameter:
5633 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5634 
5635    Level: advanced
5636 
5637 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5638 @*/
5639 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5640 {
5641   PetscFunctionBegin;
5642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5643   PetscValidBoolPointer(assembled, 2);
5644   *assembled = mat->assembled;
5645   PetscFunctionReturn(0);
5646 }
5647 
5648 /*@
5649    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5650    be called after `MatAssemblyBegin()`.
5651 
5652    Collective on Mat
5653 
5654    Input Parameters:
5655 +  mat - the matrix
5656 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5657 
5658    Options Database Keys:
5659 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5660 .  -mat_view ::ascii_info_detail - Prints more detailed info
5661 .  -mat_view - Prints matrix in ASCII format
5662 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5663 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5664 .  -display <name> - Sets display name (default is host)
5665 .  -draw_pause <sec> - Sets number of seconds to pause after display
5666 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5667 .  -viewer_socket_machine <machine> - Machine to use for socket
5668 .  -viewer_socket_port <port> - Port number to use for socket
5669 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5670 
5671    Level: beginner
5672 
5673 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5674 @*/
5675 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5676 {
5677   static PetscInt inassm = 0;
5678   PetscBool       flg    = PETSC_FALSE;
5679 
5680   PetscFunctionBegin;
5681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5682   PetscValidType(mat, 1);
5683 
5684   inassm++;
5685   MatAssemblyEnd_InUse++;
5686   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5687     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5688     PetscTryTypeMethod(mat, assemblyend, type);
5689     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5690   } else PetscTryTypeMethod(mat, assemblyend, type);
5691 
5692   /* Flush assembly is not a true assembly */
5693   if (type != MAT_FLUSH_ASSEMBLY) {
5694     if (mat->num_ass) {
5695       if (!mat->symmetry_eternal) {
5696         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5697         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5698       }
5699       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5700       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5701     }
5702     mat->num_ass++;
5703     mat->assembled        = PETSC_TRUE;
5704     mat->ass_nonzerostate = mat->nonzerostate;
5705   }
5706 
5707   mat->insertmode = NOT_SET_VALUES;
5708   MatAssemblyEnd_InUse--;
5709   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5710   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5711     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5712 
5713     if (mat->checksymmetryonassembly) {
5714       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5715       if (flg) {
5716         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5717       } else {
5718         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5719       }
5720     }
5721     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5722   }
5723   inassm--;
5724   PetscFunctionReturn(0);
5725 }
5726 
5727 /*@
5728    MatSetOption - Sets a parameter option for a matrix. Some options
5729    may be specific to certain storage formats.  Some options
5730    determine how values will be inserted (or added). Sorted,
5731    row-oriented input will generally assemble the fastest. The default
5732    is row-oriented.
5733 
5734    Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5735 
5736    Input Parameters:
5737 +  mat - the matrix
5738 .  option - the option, one of those listed below (and possibly others),
5739 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5740 
5741   Options Describing Matrix Structure:
5742 +    `MAT_SPD` - symmetric positive definite
5743 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5744 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5745 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5746 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5747 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5748 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5749 
5750    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5751    do not need to be computed (usually at a high cost)
5752 
5753    Options For Use with `MatSetValues()`:
5754    Insert a logically dense subblock, which can be
5755 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5756 
5757    Note these options reflect the data you pass in with `MatSetValues()`; it has
5758    nothing to do with how the data is stored internally in the matrix
5759    data structure.
5760 
5761    When (re)assembling a matrix, we can restrict the input for
5762    efficiency/debugging purposes.  These options include
5763 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5764 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5765 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5766 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5767 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5768 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5769         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5770         performance for very large process counts.
5771 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5772         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5773         functions, instead sending only neighbor messages.
5774 
5775    Notes:
5776    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5777 
5778    Some options are relevant only for particular matrix types and
5779    are thus ignored by others.  Other options are not supported by
5780    certain matrix types and will generate an error message if set.
5781 
5782    If using a Fortran 77 module to compute a matrix, one may need to
5783    use the column-oriented option (or convert to the row-oriented
5784    format).
5785 
5786    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5787    that would generate a new entry in the nonzero structure is instead
5788    ignored.  Thus, if memory has not alredy been allocated for this particular
5789    data, then the insertion is ignored. For dense matrices, in which
5790    the entire array is allocated, no entries are ever ignored.
5791    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5792 
5793    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5794    that would generate a new entry in the nonzero structure instead produces
5795    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
5796 
5797    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5798    that would generate a new entry that has not been preallocated will
5799    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5800    only.) This is a useful flag when debugging matrix memory preallocation.
5801    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5802 
5803    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5804    other processors should be dropped, rather than stashed.
5805    This is useful if you know that the "owning" processor is also
5806    always generating the correct matrix entries, so that PETSc need
5807    not transfer duplicate entries generated on another processor.
5808 
5809    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5810    searches during matrix assembly. When this flag is set, the hash table
5811    is created during the first matrix assembly. This hash table is
5812    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5813    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5814    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5815    supported by` MATMPIBAIJ` format only.
5816 
5817    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5818    are kept in the nonzero structure
5819 
5820    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5821    a zero location in the matrix
5822 
5823    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5824 
5825    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5826         zero row routines and thus improves performance for very large process counts.
5827 
5828    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5829         part of the matrix (since they should match the upper triangular part).
5830 
5831    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5832                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5833                      with finite difference schemes with non-periodic boundary conditions.
5834 
5835    Developer Note:
5836    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5837    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5838    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5839    not changed.
5840 
5841    Level: intermediate
5842 
5843 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5844 @*/
5845 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5846 {
5847   PetscFunctionBegin;
5848   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5849   if (op > 0) {
5850     PetscValidLogicalCollectiveEnum(mat, op, 2);
5851     PetscValidLogicalCollectiveBool(mat, flg, 3);
5852   }
5853 
5854   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);
5855 
5856   switch (op) {
5857   case MAT_FORCE_DIAGONAL_ENTRIES:
5858     mat->force_diagonals = flg;
5859     PetscFunctionReturn(0);
5860   case MAT_NO_OFF_PROC_ENTRIES:
5861     mat->nooffprocentries = flg;
5862     PetscFunctionReturn(0);
5863   case MAT_SUBSET_OFF_PROC_ENTRIES:
5864     mat->assembly_subset = flg;
5865     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5866 #if !defined(PETSC_HAVE_MPIUNI)
5867       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5868 #endif
5869       mat->stash.first_assembly_done = PETSC_FALSE;
5870     }
5871     PetscFunctionReturn(0);
5872   case MAT_NO_OFF_PROC_ZERO_ROWS:
5873     mat->nooffproczerorows = flg;
5874     PetscFunctionReturn(0);
5875   case MAT_SPD:
5876     if (flg) {
5877       mat->spd                    = PETSC_BOOL3_TRUE;
5878       mat->symmetric              = PETSC_BOOL3_TRUE;
5879       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5880     } else {
5881       mat->spd = PETSC_BOOL3_FALSE;
5882     }
5883     break;
5884   case MAT_SYMMETRIC:
5885     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5886     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5887 #if !defined(PETSC_USE_COMPLEX)
5888     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5889 #endif
5890     break;
5891   case MAT_HERMITIAN:
5892     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5893     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5894 #if !defined(PETSC_USE_COMPLEX)
5895     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5896 #endif
5897     break;
5898   case MAT_STRUCTURALLY_SYMMETRIC:
5899     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5900     break;
5901   case MAT_SYMMETRY_ETERNAL:
5902     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");
5903     mat->symmetry_eternal = flg;
5904     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5905     break;
5906   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5907     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");
5908     mat->structural_symmetry_eternal = flg;
5909     break;
5910   case MAT_SPD_ETERNAL:
5911     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");
5912     mat->spd_eternal = flg;
5913     if (flg) {
5914       mat->structural_symmetry_eternal = PETSC_TRUE;
5915       mat->symmetry_eternal            = PETSC_TRUE;
5916     }
5917     break;
5918   case MAT_STRUCTURE_ONLY:
5919     mat->structure_only = flg;
5920     break;
5921   case MAT_SORTED_FULL:
5922     mat->sortedfull = flg;
5923     break;
5924   default:
5925     break;
5926   }
5927   PetscTryTypeMethod(mat, setoption, op, flg);
5928   PetscFunctionReturn(0);
5929 }
5930 
5931 /*@
5932    MatGetOption - Gets a parameter option that has been set for a matrix.
5933 
5934    Logically Collective on mat
5935 
5936    Input Parameters:
5937 +  mat - the matrix
5938 -  option - the option, this only responds to certain options, check the code for which ones
5939 
5940    Output Parameter:
5941 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5942 
5943     Notes:
5944     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5945 
5946     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5947     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5948 
5949    Level: intermediate
5950 
5951 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5952     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5953 @*/
5954 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5955 {
5956   PetscFunctionBegin;
5957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5958   PetscValidType(mat, 1);
5959 
5960   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);
5961   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()");
5962 
5963   switch (op) {
5964   case MAT_NO_OFF_PROC_ENTRIES:
5965     *flg = mat->nooffprocentries;
5966     break;
5967   case MAT_NO_OFF_PROC_ZERO_ROWS:
5968     *flg = mat->nooffproczerorows;
5969     break;
5970   case MAT_SYMMETRIC:
5971     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5972     break;
5973   case MAT_HERMITIAN:
5974     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5975     break;
5976   case MAT_STRUCTURALLY_SYMMETRIC:
5977     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5978     break;
5979   case MAT_SPD:
5980     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
5981     break;
5982   case MAT_SYMMETRY_ETERNAL:
5983     *flg = mat->symmetry_eternal;
5984     break;
5985   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5986     *flg = mat->symmetry_eternal;
5987     break;
5988   default:
5989     break;
5990   }
5991   PetscFunctionReturn(0);
5992 }
5993 
5994 /*@
5995    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5996    this routine retains the old nonzero structure.
5997 
5998    Logically Collective on mat
5999 
6000    Input Parameters:
6001 .  mat - the matrix
6002 
6003    Level: intermediate
6004 
6005    Note:
6006     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.
6007    See the Performance chapter of the users manual for information on preallocating matrices.
6008 
6009 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6010 @*/
6011 PetscErrorCode MatZeroEntries(Mat mat)
6012 {
6013   PetscFunctionBegin;
6014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6015   PetscValidType(mat, 1);
6016   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6017   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");
6018   MatCheckPreallocated(mat, 1);
6019 
6020   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6021   PetscUseTypeMethod(mat, zeroentries);
6022   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6023   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6024   PetscFunctionReturn(0);
6025 }
6026 
6027 /*@
6028    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6029    of a set of rows and columns of a matrix.
6030 
6031    Collective on mat
6032 
6033    Input Parameters:
6034 +  mat - the matrix
6035 .  numRows - the number of rows to remove
6036 .  rows - the global row indices
6037 .  diag - value put in the diagonal of the eliminated rows
6038 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6039 -  b - optional vector of right hand side, that will be adjusted by provided solution
6040 
6041    Notes:
6042    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6043 
6044    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6045    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
6046 
6047    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6048    Krylov method to take advantage of the known solution on the zeroed rows.
6049 
6050    For the parallel case, all processes that share the matrix (i.e.,
6051    those in the communicator used for matrix creation) MUST call this
6052    routine, regardless of whether any rows being zeroed are owned by
6053    them.
6054 
6055    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6056 
6057    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6058    list only rows local to itself).
6059 
6060    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6061 
6062    Level: intermediate
6063 
6064 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6065           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6066 @*/
6067 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6068 {
6069   PetscFunctionBegin;
6070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6071   PetscValidType(mat, 1);
6072   if (numRows) PetscValidIntPointer(rows, 3);
6073   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6074   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6075   MatCheckPreallocated(mat, 1);
6076 
6077   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6078   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6079   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6080   PetscFunctionReturn(0);
6081 }
6082 
6083 /*@
6084    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6085    of a set of rows and columns of a matrix.
6086 
6087    Collective on mat
6088 
6089    Input Parameters:
6090 +  mat - the matrix
6091 .  is - the rows to zero
6092 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6093 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6094 -  b - optional vector of right hand side, that will be adjusted by provided solution
6095 
6096    Note:
6097    See `MatZeroRowsColumns()` for details on how this routine operates.
6098 
6099    Level: intermediate
6100 
6101 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6102           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6103 @*/
6104 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6105 {
6106   PetscInt        numRows;
6107   const PetscInt *rows;
6108 
6109   PetscFunctionBegin;
6110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6111   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6112   PetscValidType(mat, 1);
6113   PetscValidType(is, 2);
6114   PetscCall(ISGetLocalSize(is, &numRows));
6115   PetscCall(ISGetIndices(is, &rows));
6116   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6117   PetscCall(ISRestoreIndices(is, &rows));
6118   PetscFunctionReturn(0);
6119 }
6120 
6121 /*@
6122    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6123    of a set of rows of a matrix.
6124 
6125    Collective on mat
6126 
6127    Input Parameters:
6128 +  mat - the matrix
6129 .  numRows - the number of rows to remove
6130 .  rows - the global row indices
6131 .  diag - value put in the diagonal of the eliminated rows
6132 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6133 -  b - optional vector of right hand side, that will be adjusted by provided solution
6134 
6135    Notes:
6136    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6137 
6138    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6139 
6140    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6141    Krylov method to take advantage of the known solution on the zeroed rows.
6142 
6143    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)
6144    from the matrix.
6145 
6146    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6147    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
6148    formats this does not alter the nonzero structure.
6149 
6150    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6151    of the matrix is not changed the values are
6152    merely zeroed.
6153 
6154    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6155    formats can optionally remove the main diagonal entry from the
6156    nonzero structure as well, by passing 0.0 as the final argument).
6157 
6158    For the parallel case, all processes that share the matrix (i.e.,
6159    those in the communicator used for matrix creation) MUST call this
6160    routine, regardless of whether any rows being zeroed are owned by
6161    them.
6162 
6163    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6164    list only rows local to itself).
6165 
6166    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6167    owns that are to be zeroed. This saves a global synchronization in the implementation.
6168 
6169    Level: intermediate
6170 
6171 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6172           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6173 @*/
6174 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6175 {
6176   PetscFunctionBegin;
6177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6178   PetscValidType(mat, 1);
6179   if (numRows) PetscValidIntPointer(rows, 3);
6180   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6181   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6182   MatCheckPreallocated(mat, 1);
6183 
6184   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6185   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6186   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6187   PetscFunctionReturn(0);
6188 }
6189 
6190 /*@
6191    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6192    of a set of rows of a matrix.
6193 
6194    Collective on Mat
6195 
6196    Input Parameters:
6197 +  mat - the matrix
6198 .  is - index set of rows to remove (if NULL then no row is removed)
6199 .  diag - value put in all diagonals of eliminated rows
6200 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6201 -  b - optional vector of right hand side, that will be adjusted by provided solution
6202 
6203    Note:
6204    See `MatZeroRows()` for details on how this routine operates.
6205 
6206    Level: intermediate
6207 
6208 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6209           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6210 @*/
6211 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6212 {
6213   PetscInt        numRows = 0;
6214   const PetscInt *rows    = NULL;
6215 
6216   PetscFunctionBegin;
6217   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6218   PetscValidType(mat, 1);
6219   if (is) {
6220     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6221     PetscCall(ISGetLocalSize(is, &numRows));
6222     PetscCall(ISGetIndices(is, &rows));
6223   }
6224   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6225   if (is) PetscCall(ISRestoreIndices(is, &rows));
6226   PetscFunctionReturn(0);
6227 }
6228 
6229 /*@
6230    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6231    of a set of rows of a matrix. These rows must be local to the process.
6232 
6233    Collective on mat
6234 
6235    Input Parameters:
6236 +  mat - the matrix
6237 .  numRows - the number of rows to remove
6238 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6239 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6240 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6241 -  b - optional vector of right hand side, that will be adjusted by provided solution
6242 
6243    Notes:
6244    See `MatZeroRows()` for details on how this routine operates.
6245 
6246    The grid coordinates are across the entire grid, not just the local portion
6247 
6248    In Fortran idxm and idxn should be declared as
6249 $     MatStencil idxm(4,m)
6250    and the values inserted using
6251 $    idxm(MatStencil_i,1) = i
6252 $    idxm(MatStencil_j,1) = j
6253 $    idxm(MatStencil_k,1) = k
6254 $    idxm(MatStencil_c,1) = c
6255    etc
6256 
6257    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6258    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6259    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6260    `DM_BOUNDARY_PERIODIC` boundary type.
6261 
6262    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
6263    a single value per point) you can skip filling those indices.
6264 
6265    Level: intermediate
6266 
6267 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6268           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6269 @*/
6270 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6271 {
6272   PetscInt  dim    = mat->stencil.dim;
6273   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6274   PetscInt *dims   = mat->stencil.dims + 1;
6275   PetscInt *starts = mat->stencil.starts;
6276   PetscInt *dxm    = (PetscInt *)rows;
6277   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6278 
6279   PetscFunctionBegin;
6280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6281   PetscValidType(mat, 1);
6282   if (numRows) PetscValidPointer(rows, 3);
6283 
6284   PetscCall(PetscMalloc1(numRows, &jdxm));
6285   for (i = 0; i < numRows; ++i) {
6286     /* Skip unused dimensions (they are ordered k, j, i, c) */
6287     for (j = 0; j < 3 - sdim; ++j) dxm++;
6288     /* Local index in X dir */
6289     tmp = *dxm++ - starts[0];
6290     /* Loop over remaining dimensions */
6291     for (j = 0; j < dim - 1; ++j) {
6292       /* If nonlocal, set index to be negative */
6293       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6294       /* Update local index */
6295       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6296     }
6297     /* Skip component slot if necessary */
6298     if (mat->stencil.noc) dxm++;
6299     /* Local row number */
6300     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6301   }
6302   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6303   PetscCall(PetscFree(jdxm));
6304   PetscFunctionReturn(0);
6305 }
6306 
6307 /*@
6308    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6309    of a set of rows and columns of a matrix.
6310 
6311    Collective on mat
6312 
6313    Input Parameters:
6314 +  mat - the matrix
6315 .  numRows - the number of rows/columns to remove
6316 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6317 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6318 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6319 -  b - optional vector of right hand side, that will be adjusted by provided solution
6320 
6321    Notes:
6322    See `MatZeroRowsColumns()` for details on how this routine operates.
6323 
6324    The grid coordinates are across the entire grid, not just the local portion
6325 
6326    In Fortran idxm and idxn should be declared as
6327 $     MatStencil idxm(4,m)
6328    and the values inserted using
6329 $    idxm(MatStencil_i,1) = i
6330 $    idxm(MatStencil_j,1) = j
6331 $    idxm(MatStencil_k,1) = k
6332 $    idxm(MatStencil_c,1) = c
6333    etc
6334 
6335    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6336    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6337    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6338    `DM_BOUNDARY_PERIODIC` boundary type.
6339 
6340    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
6341    a single value per point) you can skip filling those indices.
6342 
6343    Level: intermediate
6344 
6345 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6346           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6347 @*/
6348 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6349 {
6350   PetscInt  dim    = mat->stencil.dim;
6351   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6352   PetscInt *dims   = mat->stencil.dims + 1;
6353   PetscInt *starts = mat->stencil.starts;
6354   PetscInt *dxm    = (PetscInt *)rows;
6355   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6356 
6357   PetscFunctionBegin;
6358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6359   PetscValidType(mat, 1);
6360   if (numRows) PetscValidPointer(rows, 3);
6361 
6362   PetscCall(PetscMalloc1(numRows, &jdxm));
6363   for (i = 0; i < numRows; ++i) {
6364     /* Skip unused dimensions (they are ordered k, j, i, c) */
6365     for (j = 0; j < 3 - sdim; ++j) dxm++;
6366     /* Local index in X dir */
6367     tmp = *dxm++ - starts[0];
6368     /* Loop over remaining dimensions */
6369     for (j = 0; j < dim - 1; ++j) {
6370       /* If nonlocal, set index to be negative */
6371       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6372       /* Update local index */
6373       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6374     }
6375     /* Skip component slot if necessary */
6376     if (mat->stencil.noc) dxm++;
6377     /* Local row number */
6378     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6379   }
6380   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6381   PetscCall(PetscFree(jdxm));
6382   PetscFunctionReturn(0);
6383 }
6384 
6385 /*@C
6386    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6387    of a set of rows of a matrix; using local numbering of rows.
6388 
6389    Collective on mat
6390 
6391    Input Parameters:
6392 +  mat - the matrix
6393 .  numRows - the number of rows to remove
6394 .  rows - the local row indices
6395 .  diag - value put in all diagonals of eliminated rows
6396 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6397 -  b - optional vector of right hand side, that will be adjusted by provided solution
6398 
6399    Notes:
6400    Before calling `MatZeroRowsLocal()`, the user must first set the
6401    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6402 
6403    See `MatZeroRows()` for details on how this routine operates.
6404 
6405    Level: intermediate
6406 
6407 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6408           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6409 @*/
6410 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6411 {
6412   PetscFunctionBegin;
6413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6414   PetscValidType(mat, 1);
6415   if (numRows) PetscValidIntPointer(rows, 3);
6416   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6417   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6418   MatCheckPreallocated(mat, 1);
6419 
6420   if (mat->ops->zerorowslocal) {
6421     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6422   } else {
6423     IS              is, newis;
6424     const PetscInt *newRows;
6425 
6426     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6427     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6428     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6429     PetscCall(ISGetIndices(newis, &newRows));
6430     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6431     PetscCall(ISRestoreIndices(newis, &newRows));
6432     PetscCall(ISDestroy(&newis));
6433     PetscCall(ISDestroy(&is));
6434   }
6435   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6436   PetscFunctionReturn(0);
6437 }
6438 
6439 /*@
6440    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6441    of a set of rows of a matrix; using local numbering of rows.
6442 
6443    Collective on mat
6444 
6445    Input Parameters:
6446 +  mat - the matrix
6447 .  is - index set of rows to remove
6448 .  diag - value put in all diagonals of eliminated rows
6449 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6450 -  b - optional vector of right hand side, that will be adjusted by provided solution
6451 
6452    Notes:
6453    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6454    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6455 
6456    See `MatZeroRows()` for details on how this routine operates.
6457 
6458    Level: intermediate
6459 
6460 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6461           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6462 @*/
6463 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6464 {
6465   PetscInt        numRows;
6466   const PetscInt *rows;
6467 
6468   PetscFunctionBegin;
6469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6470   PetscValidType(mat, 1);
6471   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6472   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6473   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6474   MatCheckPreallocated(mat, 1);
6475 
6476   PetscCall(ISGetLocalSize(is, &numRows));
6477   PetscCall(ISGetIndices(is, &rows));
6478   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6479   PetscCall(ISRestoreIndices(is, &rows));
6480   PetscFunctionReturn(0);
6481 }
6482 
6483 /*@
6484    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6485    of a set of rows and columns of a matrix; using local numbering of rows.
6486 
6487    Collective on mat
6488 
6489    Input Parameters:
6490 +  mat - the matrix
6491 .  numRows - the number of rows to remove
6492 .  rows - the global row indices
6493 .  diag - value put in all diagonals of eliminated rows
6494 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6495 -  b - optional vector of right hand side, that will be adjusted by provided solution
6496 
6497    Notes:
6498    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6499    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6500 
6501    See `MatZeroRowsColumns()` for details on how this routine operates.
6502 
6503    Level: intermediate
6504 
6505 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6506           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6507 @*/
6508 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6509 {
6510   IS              is, newis;
6511   const PetscInt *newRows;
6512 
6513   PetscFunctionBegin;
6514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6515   PetscValidType(mat, 1);
6516   if (numRows) PetscValidIntPointer(rows, 3);
6517   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6518   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6519   MatCheckPreallocated(mat, 1);
6520 
6521   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6522   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6523   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6524   PetscCall(ISGetIndices(newis, &newRows));
6525   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6526   PetscCall(ISRestoreIndices(newis, &newRows));
6527   PetscCall(ISDestroy(&newis));
6528   PetscCall(ISDestroy(&is));
6529   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6530   PetscFunctionReturn(0);
6531 }
6532 
6533 /*@
6534    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6535    of a set of rows and columns of a matrix; using local numbering of rows.
6536 
6537    Collective on Mat
6538 
6539    Input Parameters:
6540 +  mat - the matrix
6541 .  is - index set of rows to remove
6542 .  diag - value put in all diagonals of eliminated rows
6543 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6544 -  b - optional vector of right hand side, that will be adjusted by provided solution
6545 
6546    Notes:
6547    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6548    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6549 
6550    See `MatZeroRowsColumns()` for details on how this routine operates.
6551 
6552    Level: intermediate
6553 
6554 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6555           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6556 @*/
6557 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6558 {
6559   PetscInt        numRows;
6560   const PetscInt *rows;
6561 
6562   PetscFunctionBegin;
6563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6564   PetscValidType(mat, 1);
6565   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6566   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6567   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6568   MatCheckPreallocated(mat, 1);
6569 
6570   PetscCall(ISGetLocalSize(is, &numRows));
6571   PetscCall(ISGetIndices(is, &rows));
6572   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6573   PetscCall(ISRestoreIndices(is, &rows));
6574   PetscFunctionReturn(0);
6575 }
6576 
6577 /*@C
6578    MatGetSize - Returns the numbers of rows and columns in a matrix.
6579 
6580    Not Collective
6581 
6582    Input Parameter:
6583 .  mat - the matrix
6584 
6585    Output Parameters:
6586 +  m - the number of global rows
6587 -  n - the number of global columns
6588 
6589    Note: both output parameters can be NULL on input.
6590 
6591    Level: beginner
6592 
6593 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6594 @*/
6595 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6596 {
6597   PetscFunctionBegin;
6598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6599   if (m) *m = mat->rmap->N;
6600   if (n) *n = mat->cmap->N;
6601   PetscFunctionReturn(0);
6602 }
6603 
6604 /*@C
6605    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6606    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6607 
6608    Not Collective
6609 
6610    Input Parameter:
6611 .  mat - the matrix
6612 
6613    Output Parameters:
6614 +  m - the number of local rows, use `NULL` to not obtain this value
6615 -  n - the number of local columns, use `NULL` to not obtain this value
6616 
6617    Level: beginner
6618 
6619 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6620 @*/
6621 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6622 {
6623   PetscFunctionBegin;
6624   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6625   if (m) PetscValidIntPointer(m, 2);
6626   if (n) PetscValidIntPointer(n, 3);
6627   if (m) *m = mat->rmap->n;
6628   if (n) *n = mat->cmap->n;
6629   PetscFunctionReturn(0);
6630 }
6631 
6632 /*@C
6633    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6634    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6635 
6636    Not Collective, unless matrix has not been allocated, then collective on mat
6637 
6638    Input Parameter:
6639 .  mat - the matrix
6640 
6641    Output Parameters:
6642 +  m - the global index of the first local column, use `NULL` to not obtain this value
6643 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6644 
6645    Level: developer
6646 
6647 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6648 @*/
6649 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6650 {
6651   PetscFunctionBegin;
6652   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6653   PetscValidType(mat, 1);
6654   if (m) PetscValidIntPointer(m, 2);
6655   if (n) PetscValidIntPointer(n, 3);
6656   MatCheckPreallocated(mat, 1);
6657   if (m) *m = mat->cmap->rstart;
6658   if (n) *n = mat->cmap->rend;
6659   PetscFunctionReturn(0);
6660 }
6661 
6662 /*@C
6663    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6664    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
6665    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6666 
6667    Not Collective
6668 
6669    Input Parameter:
6670 .  mat - the matrix
6671 
6672    Output Parameters:
6673 +  m - the global index of the first local row, use `NULL` to not obtain this value
6674 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6675 
6676    Note:
6677   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6678   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6679   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6680 
6681    Level: beginner
6682 
6683 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6684           `PetscLayout`
6685 @*/
6686 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6687 {
6688   PetscFunctionBegin;
6689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6690   PetscValidType(mat, 1);
6691   if (m) PetscValidIntPointer(m, 2);
6692   if (n) PetscValidIntPointer(n, 3);
6693   MatCheckPreallocated(mat, 1);
6694   if (m) *m = mat->rmap->rstart;
6695   if (n) *n = mat->rmap->rend;
6696   PetscFunctionReturn(0);
6697 }
6698 
6699 /*@C
6700    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6701    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
6702    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6703 
6704    Not Collective, unless matrix has not been allocated, then collective on mat
6705 
6706    Input Parameters:
6707 .  mat - the matrix
6708 
6709    Output Parameters:
6710 .  ranges - start of each processors portion plus one more than the total length at the end
6711 
6712    Level: beginner
6713 
6714 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6715 @*/
6716 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6717 {
6718   PetscFunctionBegin;
6719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6720   PetscValidType(mat, 1);
6721   MatCheckPreallocated(mat, 1);
6722   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6723   PetscFunctionReturn(0);
6724 }
6725 
6726 /*@C
6727    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6728    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6729 
6730    Not Collective, unless matrix has not been allocated, then collective on Mat
6731 
6732    Input Parameters:
6733 .  mat - the matrix
6734 
6735    Output Parameters:
6736 .  ranges - start of each processors portion plus one more then the total length at the end
6737 
6738    Level: beginner
6739 
6740 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6741 @*/
6742 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6743 {
6744   PetscFunctionBegin;
6745   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6746   PetscValidType(mat, 1);
6747   MatCheckPreallocated(mat, 1);
6748   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6749   PetscFunctionReturn(0);
6750 }
6751 
6752 /*@C
6753    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6754    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6755    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6756 
6757    Not Collective
6758 
6759    Input Parameter:
6760 .  A - matrix
6761 
6762    Output Parameters:
6763 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6764 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6765 
6766    Level: intermediate
6767 
6768 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6769 @*/
6770 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6771 {
6772   PetscErrorCode (*f)(Mat, IS *, IS *);
6773 
6774   PetscFunctionBegin;
6775   MatCheckPreallocated(A, 1);
6776   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6777   if (f) {
6778     PetscCall((*f)(A, rows, cols));
6779   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6780     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6781     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6782   }
6783   PetscFunctionReturn(0);
6784 }
6785 
6786 /*@C
6787    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6788    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6789    to complete the factorization.
6790 
6791    Collective on fact
6792 
6793    Input Parameters:
6794 +  fact - the factorized matrix obtained with `MatGetFactor()`
6795 .  mat - the matrix
6796 .  row - row permutation
6797 .  column - column permutation
6798 -  info - structure containing
6799 $      levels - number of levels of fill.
6800 $      expected fill - as ratio of original fill.
6801 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6802                 missing diagonal entries)
6803 
6804    Output Parameters:
6805 .  fact - new matrix that has been symbolically factored
6806 
6807    Level: developer
6808 
6809    Notes:
6810    See [Matrix Factorization](sec_matfactor) for additional information.
6811 
6812    Most users should employ the `KSP` interface for linear solvers
6813    instead of working directly with matrix algebra routines such as this.
6814    See, e.g., `KSPCreate()`.
6815 
6816    Uses the definition of level of fill as in Y. Saad, 2003
6817 
6818    Developer Note:
6819    The Fortran interface is not autogenerated as the f90
6820    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6821 
6822    References:
6823 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6824 
6825 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6826           `MatGetOrdering()`, `MatFactorInfo`
6827 @*/
6828 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6829 {
6830   PetscFunctionBegin;
6831   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6832   PetscValidType(mat, 2);
6833   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6834   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6835   PetscValidPointer(info, 5);
6836   PetscValidPointer(fact, 1);
6837   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6838   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6839   if (!fact->ops->ilufactorsymbolic) {
6840     MatSolverType stype;
6841     PetscCall(MatFactorGetSolverType(fact, &stype));
6842     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6843   }
6844   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6845   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6846   MatCheckPreallocated(mat, 2);
6847 
6848   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6849   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6850   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6851   PetscFunctionReturn(0);
6852 }
6853 
6854 /*@C
6855    MatICCFactorSymbolic - Performs symbolic incomplete
6856    Cholesky factorization for a symmetric matrix.  Use
6857    `MatCholeskyFactorNumeric()` to complete the factorization.
6858 
6859    Collective on fact
6860 
6861    Input Parameters:
6862 +  fact - the factorized matrix obtained with `MatGetFactor()`
6863 .  mat - the matrix to be factored
6864 .  perm - row and column permutation
6865 -  info - structure containing
6866 $      levels - number of levels of fill.
6867 $      expected fill - as ratio of original fill.
6868 
6869    Output Parameter:
6870 .  fact - the factored matrix
6871 
6872    Level: developer
6873 
6874    Notes:
6875    Most users should employ the `KSP` interface for linear solvers
6876    instead of working directly with matrix algebra routines such as this.
6877    See, e.g., `KSPCreate()`.
6878 
6879    This uses the definition of level of fill as in Y. Saad, 2003
6880 
6881    Developer Note:
6882    The Fortran interface is not autogenerated as the f90
6883    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6884 
6885    References:
6886 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6887 
6888 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6889 @*/
6890 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6891 {
6892   PetscFunctionBegin;
6893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6894   PetscValidType(mat, 2);
6895   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6896   PetscValidPointer(info, 4);
6897   PetscValidPointer(fact, 1);
6898   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6899   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6900   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6901   if (!(fact)->ops->iccfactorsymbolic) {
6902     MatSolverType stype;
6903     PetscCall(MatFactorGetSolverType(fact, &stype));
6904     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6905   }
6906   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6907   MatCheckPreallocated(mat, 2);
6908 
6909   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6910   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6911   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6912   PetscFunctionReturn(0);
6913 }
6914 
6915 /*@C
6916    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6917    points to an array of valid matrices, they may be reused to store the new
6918    submatrices.
6919 
6920    Collective on mat
6921 
6922    Input Parameters:
6923 +  mat - the matrix
6924 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6925 .  irow, icol - index sets of rows and columns to extract
6926 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6927 
6928    Output Parameter:
6929 .  submat - the array of submatrices
6930 
6931    Notes:
6932    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6933    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6934    to extract a parallel submatrix.
6935 
6936    Some matrix types place restrictions on the row and column
6937    indices, such as that they be sorted or that they be equal to each other.
6938 
6939    The index sets may not have duplicate entries.
6940 
6941    When extracting submatrices from a parallel matrix, each processor can
6942    form a different submatrix by setting the rows and columns of its
6943    individual index sets according to the local submatrix desired.
6944 
6945    When finished using the submatrices, the user should destroy
6946    them with `MatDestroySubMatrices()`.
6947 
6948    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6949    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6950 
6951    This routine creates the matrices in submat; you should NOT create them before
6952    calling it. It also allocates the array of matrix pointers submat.
6953 
6954    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6955    request one row/column in a block, they must request all rows/columns that are in
6956    that block. For example, if the block size is 2 you cannot request just row 0 and
6957    column 0.
6958 
6959    Fortran Note:
6960    The Fortran interface is slightly different from that given below; it
6961    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
6962 
6963    Level: advanced
6964 
6965 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6966 @*/
6967 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6968 {
6969   PetscInt  i;
6970   PetscBool eq;
6971 
6972   PetscFunctionBegin;
6973   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6974   PetscValidType(mat, 1);
6975   if (n) {
6976     PetscValidPointer(irow, 3);
6977     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6978     PetscValidPointer(icol, 4);
6979     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6980   }
6981   PetscValidPointer(submat, 6);
6982   if (n && scall == MAT_REUSE_MATRIX) {
6983     PetscValidPointer(*submat, 6);
6984     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
6985   }
6986   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6987   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6988   MatCheckPreallocated(mat, 1);
6989   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6990   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6991   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6992   for (i = 0; i < n; i++) {
6993     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6994     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6995     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6996 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6997     if (mat->boundtocpu && mat->bindingpropagates) {
6998       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
6999       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7000     }
7001 #endif
7002   }
7003   PetscFunctionReturn(0);
7004 }
7005 
7006 /*@C
7007    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7008 
7009    Collective on mat
7010 
7011    Input Parameters:
7012 +  mat - the matrix
7013 .  n   - the number of submatrixes to be extracted
7014 .  irow, icol - index sets of rows and columns to extract
7015 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7016 
7017    Output Parameter:
7018 .  submat - the array of submatrices
7019 
7020    Level: advanced
7021 
7022    Note:
7023    This is used by `PCGASM`
7024 
7025 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7026 @*/
7027 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7028 {
7029   PetscInt  i;
7030   PetscBool eq;
7031 
7032   PetscFunctionBegin;
7033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7034   PetscValidType(mat, 1);
7035   if (n) {
7036     PetscValidPointer(irow, 3);
7037     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7038     PetscValidPointer(icol, 4);
7039     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7040   }
7041   PetscValidPointer(submat, 6);
7042   if (n && scall == MAT_REUSE_MATRIX) {
7043     PetscValidPointer(*submat, 6);
7044     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7045   }
7046   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7047   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7048   MatCheckPreallocated(mat, 1);
7049 
7050   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7051   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7052   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7053   for (i = 0; i < n; i++) {
7054     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7055     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7056   }
7057   PetscFunctionReturn(0);
7058 }
7059 
7060 /*@C
7061    MatDestroyMatrices - Destroys an array of matrices.
7062 
7063    Collective on mat
7064 
7065    Input Parameters:
7066 +  n - the number of local matrices
7067 -  mat - the matrices (note that this is a pointer to the array of matrices)
7068 
7069    Level: advanced
7070 
7071     Note:
7072     Frees not only the matrices, but also the array that contains the matrices
7073            In Fortran will not free the array.
7074 
7075 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7076 @*/
7077 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7078 {
7079   PetscInt i;
7080 
7081   PetscFunctionBegin;
7082   if (!*mat) PetscFunctionReturn(0);
7083   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7084   PetscValidPointer(mat, 2);
7085 
7086   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7087 
7088   /* memory is allocated even if n = 0 */
7089   PetscCall(PetscFree(*mat));
7090   PetscFunctionReturn(0);
7091 }
7092 
7093 /*@C
7094    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7095 
7096    Collective on mat
7097 
7098    Input Parameters:
7099 +  n - the number of local matrices
7100 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7101                        sequence of MatCreateSubMatrices())
7102 
7103    Level: advanced
7104 
7105     Note:
7106     Frees not only the matrices, but also the array that contains the matrices
7107            In Fortran will not free the array.
7108 
7109 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7110 @*/
7111 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7112 {
7113   Mat mat0;
7114 
7115   PetscFunctionBegin;
7116   if (!*mat) PetscFunctionReturn(0);
7117   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7118   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7119   PetscValidPointer(mat, 2);
7120 
7121   mat0 = (*mat)[0];
7122   if (mat0 && mat0->ops->destroysubmatrices) {
7123     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7124   } else {
7125     PetscCall(MatDestroyMatrices(n, mat));
7126   }
7127   PetscFunctionReturn(0);
7128 }
7129 
7130 /*@C
7131    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7132 
7133    Collective on mat
7134 
7135    Input Parameters:
7136 .  mat - the matrix
7137 
7138    Output Parameter:
7139 .  matstruct - the sequential matrix with the nonzero structure of mat
7140 
7141   Level: developer
7142 
7143 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7144 @*/
7145 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7146 {
7147   PetscFunctionBegin;
7148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7149   PetscValidPointer(matstruct, 2);
7150 
7151   PetscValidType(mat, 1);
7152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7153   MatCheckPreallocated(mat, 1);
7154 
7155   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7156   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7157   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7158   PetscFunctionReturn(0);
7159 }
7160 
7161 /*@C
7162    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7163 
7164    Collective on mat
7165 
7166    Input Parameters:
7167 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7168                        sequence of `MatGetSequentialNonzeroStructure()`)
7169 
7170    Level: advanced
7171 
7172     Note:
7173     Frees not only the matrices, but also the array that contains the matrices
7174 
7175 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7176 @*/
7177 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7178 {
7179   PetscFunctionBegin;
7180   PetscValidPointer(mat, 1);
7181   PetscCall(MatDestroy(mat));
7182   PetscFunctionReturn(0);
7183 }
7184 
7185 /*@
7186    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7187    replaces the index sets by larger ones that represent submatrices with
7188    additional overlap.
7189 
7190    Collective on mat
7191 
7192    Input Parameters:
7193 +  mat - the matrix
7194 .  n   - the number of index sets
7195 .  is  - the array of index sets (these index sets will changed during the call)
7196 -  ov  - the additional overlap requested
7197 
7198    Options Database:
7199 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7200 
7201    Level: developer
7202 
7203    Developer Note:
7204    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.
7205 
7206 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7207 @*/
7208 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7209 {
7210   PetscInt i, bs, cbs;
7211 
7212   PetscFunctionBegin;
7213   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7214   PetscValidType(mat, 1);
7215   PetscValidLogicalCollectiveInt(mat, n, 2);
7216   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7217   if (n) {
7218     PetscValidPointer(is, 3);
7219     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7220   }
7221   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7222   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7223   MatCheckPreallocated(mat, 1);
7224 
7225   if (!ov || !n) PetscFunctionReturn(0);
7226   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7227   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7228   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7229   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7230   if (bs == cbs) {
7231     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7232   }
7233   PetscFunctionReturn(0);
7234 }
7235 
7236 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7237 
7238 /*@
7239    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7240    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7241    additional overlap.
7242 
7243    Collective on mat
7244 
7245    Input Parameters:
7246 +  mat - the matrix
7247 .  n   - the number of index sets
7248 .  is  - the array of index sets (these index sets will changed during the call)
7249 -  ov  - the additional overlap requested
7250 
7251 `   Options Database:
7252 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7253 
7254    Level: developer
7255 
7256 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7257 @*/
7258 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7259 {
7260   PetscInt i;
7261 
7262   PetscFunctionBegin;
7263   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7264   PetscValidType(mat, 1);
7265   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7266   if (n) {
7267     PetscValidPointer(is, 3);
7268     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7269   }
7270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7271   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7272   MatCheckPreallocated(mat, 1);
7273   if (!ov) PetscFunctionReturn(0);
7274   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7275   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7276   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7277   PetscFunctionReturn(0);
7278 }
7279 
7280 /*@
7281    MatGetBlockSize - Returns the matrix block size.
7282 
7283    Not Collective
7284 
7285    Input Parameter:
7286 .  mat - the matrix
7287 
7288    Output Parameter:
7289 .  bs - block size
7290 
7291    Notes:
7292     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7293 
7294    If the block size has not been set yet this routine returns 1.
7295 
7296    Level: intermediate
7297 
7298 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7299 @*/
7300 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7301 {
7302   PetscFunctionBegin;
7303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7304   PetscValidIntPointer(bs, 2);
7305   *bs = PetscAbs(mat->rmap->bs);
7306   PetscFunctionReturn(0);
7307 }
7308 
7309 /*@
7310    MatGetBlockSizes - Returns the matrix block row and column sizes.
7311 
7312    Not Collective
7313 
7314    Input Parameter:
7315 .  mat - the matrix
7316 
7317    Output Parameters:
7318 +  rbs - row block size
7319 -  cbs - column block size
7320 
7321    Notes:
7322     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7323     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7324 
7325    If a block size has not been set yet this routine returns 1.
7326 
7327    Level: intermediate
7328 
7329 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7330 @*/
7331 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7332 {
7333   PetscFunctionBegin;
7334   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7335   if (rbs) PetscValidIntPointer(rbs, 2);
7336   if (cbs) PetscValidIntPointer(cbs, 3);
7337   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7338   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7339   PetscFunctionReturn(0);
7340 }
7341 
7342 /*@
7343    MatSetBlockSize - Sets the matrix block size.
7344 
7345    Logically Collective on mat
7346 
7347    Input Parameters:
7348 +  mat - the matrix
7349 -  bs - block size
7350 
7351    Notes:
7352     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7353     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7354 
7355     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7356     is compatible with the matrix local sizes.
7357 
7358    Level: intermediate
7359 
7360 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7361 @*/
7362 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7363 {
7364   PetscFunctionBegin;
7365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7366   PetscValidLogicalCollectiveInt(mat, bs, 2);
7367   PetscCall(MatSetBlockSizes(mat, bs, bs));
7368   PetscFunctionReturn(0);
7369 }
7370 
7371 typedef struct {
7372   PetscInt         n;
7373   IS              *is;
7374   Mat             *mat;
7375   PetscObjectState nonzerostate;
7376   Mat              C;
7377 } EnvelopeData;
7378 
7379 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7380 {
7381   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7382   PetscCall(PetscFree(edata->is));
7383   PetscCall(PetscFree(edata));
7384   return 0;
7385 }
7386 
7387 /*
7388    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7389          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7390 
7391    Collective on mat
7392 
7393    Input Parameter:
7394 .  mat - the matrix
7395 
7396    Notes:
7397      There can be zeros within the blocks
7398 
7399      The blocks can overlap between processes, including laying on more than two processes
7400 
7401 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7402 */
7403 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7404 {
7405   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7406   PetscInt          *diag, *odiag, sc;
7407   VecScatter         scatter;
7408   PetscScalar       *seqv;
7409   const PetscScalar *parv;
7410   const PetscInt    *ia, *ja;
7411   PetscBool          set, flag, done;
7412   Mat                AA = mat, A;
7413   MPI_Comm           comm;
7414   PetscMPIInt        rank, size, tag;
7415   MPI_Status         status;
7416   PetscContainer     container;
7417   EnvelopeData      *edata;
7418   Vec                seq, par;
7419   IS                 isglobal;
7420 
7421   PetscFunctionBegin;
7422   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7423   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7424   if (!set || !flag) {
7425     /* TOO: only needs nonzero structure of transpose */
7426     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7427     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7428   }
7429   PetscCall(MatAIJGetLocalMat(AA, &A));
7430   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7431   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7432 
7433   PetscCall(MatGetLocalSize(mat, &n, NULL));
7434   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7435   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7436   PetscCallMPI(MPI_Comm_size(comm, &size));
7437   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7438 
7439   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7440 
7441   if (rank > 0) {
7442     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7443     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7444   }
7445   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7446   for (i = 0; i < n; i++) {
7447     env = PetscMax(env, ja[ia[i + 1] - 1]);
7448     II  = rstart + i;
7449     if (env == II) {
7450       starts[lblocks]  = tbs;
7451       sizes[lblocks++] = 1 + II - tbs;
7452       tbs              = 1 + II;
7453     }
7454   }
7455   if (rank < size - 1) {
7456     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7457     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7458   }
7459 
7460   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7461   if (!set || !flag) PetscCall(MatDestroy(&AA));
7462   PetscCall(MatDestroy(&A));
7463 
7464   PetscCall(PetscNew(&edata));
7465   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7466   edata->n = lblocks;
7467   /* create IS needed for extracting blocks from the original matrix */
7468   PetscCall(PetscMalloc1(lblocks, &edata->is));
7469   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7470 
7471   /* Create the resulting inverse matrix structure with preallocation information */
7472   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7473   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7474   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7475   PetscCall(MatSetType(edata->C, MATAIJ));
7476 
7477   /* Communicate the start and end of each row, from each block to the correct rank */
7478   /* TODO: Use PetscSF instead of VecScatter */
7479   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7480   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7481   PetscCall(VecGetArrayWrite(seq, &seqv));
7482   for (PetscInt i = 0; i < lblocks; i++) {
7483     for (PetscInt j = 0; j < sizes[i]; j++) {
7484       seqv[cnt]     = starts[i];
7485       seqv[cnt + 1] = starts[i] + sizes[i];
7486       cnt += 2;
7487     }
7488   }
7489   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7490   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7491   sc -= cnt;
7492   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7493   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7494   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7495   PetscCall(ISDestroy(&isglobal));
7496   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7497   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7498   PetscCall(VecScatterDestroy(&scatter));
7499   PetscCall(VecDestroy(&seq));
7500   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7501   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7502   PetscCall(VecGetArrayRead(par, &parv));
7503   cnt = 0;
7504   PetscCall(MatGetSize(mat, NULL, &n));
7505   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7506     PetscInt start, end, d = 0, od = 0;
7507 
7508     start = (PetscInt)PetscRealPart(parv[cnt]);
7509     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7510     cnt += 2;
7511 
7512     if (start < cstart) {
7513       od += cstart - start + n - cend;
7514       d += cend - cstart;
7515     } else if (start < cend) {
7516       od += n - cend;
7517       d += cend - start;
7518     } else od += n - start;
7519     if (end <= cstart) {
7520       od -= cstart - end + n - cend;
7521       d -= cend - cstart;
7522     } else if (end < cend) {
7523       od -= n - cend;
7524       d -= cend - end;
7525     } else od -= n - end;
7526 
7527     odiag[i] = od;
7528     diag[i]  = d;
7529   }
7530   PetscCall(VecRestoreArrayRead(par, &parv));
7531   PetscCall(VecDestroy(&par));
7532   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7533   PetscCall(PetscFree2(diag, odiag));
7534   PetscCall(PetscFree2(sizes, starts));
7535 
7536   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7537   PetscCall(PetscContainerSetPointer(container, edata));
7538   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7539   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7540   PetscCall(PetscObjectDereference((PetscObject)container));
7541   PetscFunctionReturn(0);
7542 }
7543 
7544 /*@
7545   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7546 
7547   Collective on A
7548 
7549   Input Parameters:
7550 . A - the matrix
7551 
7552   Output Parameters:
7553 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7554 
7555   Note:
7556      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7557 
7558   Level: advanced
7559 
7560 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7561 @*/
7562 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7563 {
7564   PetscContainer   container;
7565   EnvelopeData    *edata;
7566   PetscObjectState nonzerostate;
7567 
7568   PetscFunctionBegin;
7569   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7570   if (!container) {
7571     PetscCall(MatComputeVariableBlockEnvelope(A));
7572     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7573   }
7574   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7575   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7576   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7577   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7578 
7579   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7580   *C = edata->C;
7581 
7582   for (PetscInt i = 0; i < edata->n; i++) {
7583     Mat          D;
7584     PetscScalar *dvalues;
7585 
7586     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7587     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7588     PetscCall(MatSeqDenseInvert(D));
7589     PetscCall(MatDenseGetArray(D, &dvalues));
7590     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7591     PetscCall(MatDestroy(&D));
7592   }
7593   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7594   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7595   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7596   PetscFunctionReturn(0);
7597 }
7598 
7599 /*@
7600    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7601 
7602    Logically Collective on mat
7603 
7604    Input Parameters:
7605 +  mat - the matrix
7606 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7607 -  bsizes - the block sizes
7608 
7609    Notes:
7610     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7611 
7612     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.
7613 
7614    Level: intermediate
7615 
7616 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7617           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7618 @*/
7619 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7620 {
7621   PetscInt i, ncnt = 0, nlocal;
7622 
7623   PetscFunctionBegin;
7624   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7625   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7626   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7627   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7628   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);
7629   PetscCall(PetscFree(mat->bsizes));
7630   mat->nblocks = nblocks;
7631   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7632   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7633   PetscFunctionReturn(0);
7634 }
7635 
7636 /*@C
7637    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7638 
7639    Logically Collective on mat
7640 
7641    Input Parameter:
7642 .  mat - the matrix
7643 
7644    Output Parameters:
7645 +  nblocks - the number of blocks on this process
7646 -  bsizes - the block sizes
7647 
7648    Fortran Note:
7649    Currently not supported from Fortran
7650 
7651    Level: intermediate
7652 
7653 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7654 @*/
7655 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7656 {
7657   PetscFunctionBegin;
7658   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7659   *nblocks = mat->nblocks;
7660   *bsizes  = mat->bsizes;
7661   PetscFunctionReturn(0);
7662 }
7663 
7664 /*@
7665    MatSetBlockSizes - Sets the matrix block row and column sizes.
7666 
7667    Logically Collective on mat
7668 
7669    Input Parameters:
7670 +  mat - the matrix
7671 .  rbs - row block size
7672 -  cbs - column block size
7673 
7674    Notes:
7675     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7676     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7677     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7678 
7679     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7680     are compatible with the matrix local sizes.
7681 
7682     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7683 
7684    Level: intermediate
7685 
7686 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7687 @*/
7688 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7689 {
7690   PetscFunctionBegin;
7691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7692   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7693   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7694   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7695   if (mat->rmap->refcnt) {
7696     ISLocalToGlobalMapping l2g  = NULL;
7697     PetscLayout            nmap = NULL;
7698 
7699     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7700     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7701     PetscCall(PetscLayoutDestroy(&mat->rmap));
7702     mat->rmap          = nmap;
7703     mat->rmap->mapping = l2g;
7704   }
7705   if (mat->cmap->refcnt) {
7706     ISLocalToGlobalMapping l2g  = NULL;
7707     PetscLayout            nmap = NULL;
7708 
7709     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7710     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7711     PetscCall(PetscLayoutDestroy(&mat->cmap));
7712     mat->cmap          = nmap;
7713     mat->cmap->mapping = l2g;
7714   }
7715   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7716   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7717   PetscFunctionReturn(0);
7718 }
7719 
7720 /*@
7721    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7722 
7723    Logically Collective on mat
7724 
7725    Input Parameters:
7726 +  mat - the matrix
7727 .  fromRow - matrix from which to copy row block size
7728 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7729 
7730    Level: developer
7731 
7732 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7733 @*/
7734 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7735 {
7736   PetscFunctionBegin;
7737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7738   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7739   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7740   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7741   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7742   PetscFunctionReturn(0);
7743 }
7744 
7745 /*@
7746    MatResidual - Default routine to calculate the residual r = b - Ax
7747 
7748    Collective on mat
7749 
7750    Input Parameters:
7751 +  mat - the matrix
7752 .  b   - the right-hand-side
7753 -  x   - the approximate solution
7754 
7755    Output Parameter:
7756 .  r - location to store the residual
7757 
7758    Level: developer
7759 
7760 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7761 @*/
7762 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7763 {
7764   PetscFunctionBegin;
7765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7766   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7767   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7768   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7769   PetscValidType(mat, 1);
7770   MatCheckPreallocated(mat, 1);
7771   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7772   if (!mat->ops->residual) {
7773     PetscCall(MatMult(mat, x, r));
7774     PetscCall(VecAYPX(r, -1.0, b));
7775   } else {
7776     PetscUseTypeMethod(mat, residual, b, x, r);
7777   }
7778   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7779   PetscFunctionReturn(0);
7780 }
7781 
7782 /*@C
7783     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7784 
7785    Collective on mat
7786 
7787     Input Parameters:
7788 +   mat - the matrix
7789 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7790 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7791 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7792                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7793                  always used.
7794 
7795     Output Parameters:
7796 +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7797 .   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
7798 .   ja - the column indices, use NULL if not needed
7799 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7800            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7801 
7802     Level: developer
7803 
7804     Notes:
7805     You CANNOT change any of the ia[] or ja[] values.
7806 
7807     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7808 
7809     Fortran Notes:
7810     In Fortran use
7811 $
7812 $      PetscInt ia(1), ja(1)
7813 $      PetscOffset iia, jja
7814 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7815 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7816 
7817      or
7818 $
7819 $    PetscInt, pointer :: ia(:),ja(:)
7820 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7821 $    ! Access the ith and jth entries via ia(i) and ja(j)
7822 
7823 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7824 @*/
7825 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7826 {
7827   PetscFunctionBegin;
7828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7829   PetscValidType(mat, 1);
7830   if (n) PetscValidIntPointer(n, 5);
7831   if (ia) PetscValidPointer(ia, 6);
7832   if (ja) PetscValidPointer(ja, 7);
7833   if (done) PetscValidBoolPointer(done, 8);
7834   MatCheckPreallocated(mat, 1);
7835   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7836   else {
7837     if (done) *done = PETSC_TRUE;
7838     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7839     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7840     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7841   }
7842   PetscFunctionReturn(0);
7843 }
7844 
7845 /*@C
7846     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7847 
7848     Collective on mat
7849 
7850     Input Parameters:
7851 +   mat - the matrix
7852 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7853 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7854                 symmetrized
7855 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7856                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7857                  always used.
7858 .   n - number of columns in the (possibly compressed) matrix
7859 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7860 -   ja - the row indices
7861 
7862     Output Parameters:
7863 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7864 
7865     Level: developer
7866 
7867 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7868 @*/
7869 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7870 {
7871   PetscFunctionBegin;
7872   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7873   PetscValidType(mat, 1);
7874   PetscValidIntPointer(n, 5);
7875   if (ia) PetscValidPointer(ia, 6);
7876   if (ja) PetscValidPointer(ja, 7);
7877   PetscValidBoolPointer(done, 8);
7878   MatCheckPreallocated(mat, 1);
7879   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7880   else {
7881     *done = PETSC_TRUE;
7882     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7883   }
7884   PetscFunctionReturn(0);
7885 }
7886 
7887 /*@C
7888     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7889 
7890     Collective on mat
7891 
7892     Input Parameters:
7893 +   mat - the matrix
7894 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7895 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7896 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7897                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7898                  always used.
7899 .   n - size of (possibly compressed) matrix
7900 .   ia - the row pointers
7901 -   ja - the column indices
7902 
7903     Output Parameters:
7904 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7905 
7906     Note:
7907     This routine zeros out n, ia, and ja. This is to prevent accidental
7908     us of the array after it has been restored. If you pass NULL, it will
7909     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7910 
7911     Level: developer
7912 
7913 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7914 @*/
7915 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7916 {
7917   PetscFunctionBegin;
7918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7919   PetscValidType(mat, 1);
7920   if (ia) PetscValidPointer(ia, 6);
7921   if (ja) PetscValidPointer(ja, 7);
7922   if (done) PetscValidBoolPointer(done, 8);
7923   MatCheckPreallocated(mat, 1);
7924 
7925   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7926   else {
7927     if (done) *done = PETSC_TRUE;
7928     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7929     if (n) *n = 0;
7930     if (ia) *ia = NULL;
7931     if (ja) *ja = NULL;
7932   }
7933   PetscFunctionReturn(0);
7934 }
7935 
7936 /*@C
7937     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7938 
7939     Collective on Mat
7940 
7941     Input Parameters:
7942 +   mat - the matrix
7943 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7944 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7945 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7946                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7947                  always used.
7948 
7949     Output Parameters:
7950 +   n - size of (possibly compressed) matrix
7951 .   ia - the column pointers
7952 .   ja - the row indices
7953 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7954 
7955     Level: developer
7956 
7957 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7958 @*/
7959 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7960 {
7961   PetscFunctionBegin;
7962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7963   PetscValidType(mat, 1);
7964   if (ia) PetscValidPointer(ia, 6);
7965   if (ja) PetscValidPointer(ja, 7);
7966   PetscValidBoolPointer(done, 8);
7967   MatCheckPreallocated(mat, 1);
7968 
7969   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7970   else {
7971     *done = PETSC_TRUE;
7972     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7973     if (n) *n = 0;
7974     if (ia) *ia = NULL;
7975     if (ja) *ja = NULL;
7976   }
7977   PetscFunctionReturn(0);
7978 }
7979 
7980 /*@C
7981     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7982 
7983     Collective on mat
7984 
7985     Input Parameters:
7986 +   mat - the matrix
7987 .   ncolors - max color value
7988 .   n   - number of entries in colorarray
7989 -   colorarray - array indicating color for each column
7990 
7991     Output Parameters:
7992 .   iscoloring - coloring generated using colorarray information
7993 
7994     Level: developer
7995 
7996 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7997 @*/
7998 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
7999 {
8000   PetscFunctionBegin;
8001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8002   PetscValidType(mat, 1);
8003   PetscValidIntPointer(colorarray, 4);
8004   PetscValidPointer(iscoloring, 5);
8005   MatCheckPreallocated(mat, 1);
8006 
8007   if (!mat->ops->coloringpatch) {
8008     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8009   } else {
8010     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8011   }
8012   PetscFunctionReturn(0);
8013 }
8014 
8015 /*@
8016    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8017 
8018    Logically Collective on mat
8019 
8020    Input Parameter:
8021 .  mat - the factored matrix to be reset
8022 
8023    Notes:
8024    This routine should be used only with factored matrices formed by in-place
8025    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8026    format).  This option can save memory, for example, when solving nonlinear
8027    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8028    ILU(0) preconditioner.
8029 
8030    Note that one can specify in-place ILU(0) factorization by calling
8031 .vb
8032      PCType(pc,PCILU);
8033      PCFactorSeUseInPlace(pc);
8034 .ve
8035    or by using the options -pc_type ilu -pc_factor_in_place
8036 
8037    In-place factorization ILU(0) can also be used as a local
8038    solver for the blocks within the block Jacobi or additive Schwarz
8039    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8040    for details on setting local solver options.
8041 
8042    Most users should employ the `KSP` interface for linear solvers
8043    instead of working directly with matrix algebra routines such as this.
8044    See, e.g., `KSPCreate()`.
8045 
8046    Level: developer
8047 
8048 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8049 @*/
8050 PetscErrorCode MatSetUnfactored(Mat mat)
8051 {
8052   PetscFunctionBegin;
8053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8054   PetscValidType(mat, 1);
8055   MatCheckPreallocated(mat, 1);
8056   mat->factortype = MAT_FACTOR_NONE;
8057   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8058   PetscUseTypeMethod(mat, setunfactored);
8059   PetscFunctionReturn(0);
8060 }
8061 
8062 /*MC
8063     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8064 
8065     Synopsis:
8066     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8067 
8068     Not collective
8069 
8070     Input Parameter:
8071 .   x - matrix
8072 
8073     Output Parameters:
8074 +   xx_v - the Fortran pointer to the array
8075 -   ierr - error code
8076 
8077     Example of Usage:
8078 .vb
8079       PetscScalar, pointer xx_v(:,:)
8080       ....
8081       call MatDenseGetArrayF90(x,xx_v,ierr)
8082       a = xx_v(3)
8083       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8084 .ve
8085 
8086     Level: advanced
8087 
8088 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8089 
8090 M*/
8091 
8092 /*MC
8093     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8094     accessed with `MatDenseGetArrayF90()`.
8095 
8096     Synopsis:
8097     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8098 
8099     Not collective
8100 
8101     Input Parameters:
8102 +   x - matrix
8103 -   xx_v - the Fortran90 pointer to the array
8104 
8105     Output Parameter:
8106 .   ierr - error code
8107 
8108     Example of Usage:
8109 .vb
8110        PetscScalar, pointer xx_v(:,:)
8111        ....
8112        call MatDenseGetArrayF90(x,xx_v,ierr)
8113        a = xx_v(3)
8114        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8115 .ve
8116 
8117     Level: advanced
8118 
8119 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8120 
8121 M*/
8122 
8123 /*MC
8124     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8125 
8126     Synopsis:
8127     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8128 
8129     Not collective
8130 
8131     Input Parameter:
8132 .   x - matrix
8133 
8134     Output Parameters:
8135 +   xx_v - the Fortran pointer to the array
8136 -   ierr - error code
8137 
8138     Example of Usage:
8139 .vb
8140       PetscScalar, pointer xx_v(:)
8141       ....
8142       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8143       a = xx_v(3)
8144       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8145 .ve
8146 
8147     Level: advanced
8148 
8149 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8150 
8151 M*/
8152 
8153 /*MC
8154     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8155     accessed with `MatSeqAIJGetArrayF90()`.
8156 
8157     Synopsis:
8158     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8159 
8160     Not collective
8161 
8162     Input Parameters:
8163 +   x - matrix
8164 -   xx_v - the Fortran90 pointer to the array
8165 
8166     Output Parameter:
8167 .   ierr - error code
8168 
8169     Example of Usage:
8170 .vb
8171        PetscScalar, pointer xx_v(:)
8172        ....
8173        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8174        a = xx_v(3)
8175        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8176 .ve
8177 
8178     Level: advanced
8179 
8180 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8181 
8182 M*/
8183 
8184 /*@
8185     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8186                       as the original matrix.
8187 
8188     Collective on mat
8189 
8190     Input Parameters:
8191 +   mat - the original matrix
8192 .   isrow - parallel IS containing the rows this processor should obtain
8193 .   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.
8194 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8195 
8196     Output Parameter:
8197 .   newmat - the new submatrix, of the same type as the old
8198 
8199     Level: advanced
8200 
8201     Notes:
8202     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8203 
8204     Some matrix types place restrictions on the row and column indices, such
8205     as that they be sorted or that they be equal to each other.
8206 
8207     The index sets may not have duplicate entries.
8208 
8209       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8210    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8211    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8212    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8213    you are finished using it.
8214 
8215     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8216     the input matrix.
8217 
8218     If iscol is NULL then all columns are obtained (not supported in Fortran).
8219 
8220    Example usage:
8221    Consider the following 8x8 matrix with 34 non-zero values, that is
8222    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8223    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8224    as follows:
8225 
8226 .vb
8227             1  2  0  |  0  3  0  |  0  4
8228     Proc0   0  5  6  |  7  0  0  |  8  0
8229             9  0 10  | 11  0  0  | 12  0
8230     -------------------------------------
8231            13  0 14  | 15 16 17  |  0  0
8232     Proc1   0 18  0  | 19 20 21  |  0  0
8233             0  0  0  | 22 23  0  | 24  0
8234     -------------------------------------
8235     Proc2  25 26 27  |  0  0 28  | 29  0
8236            30  0  0  | 31 32 33  |  0 34
8237 .ve
8238 
8239     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8240 
8241 .vb
8242             2  0  |  0  3  0  |  0
8243     Proc0   5  6  |  7  0  0  |  8
8244     -------------------------------
8245     Proc1  18  0  | 19 20 21  |  0
8246     -------------------------------
8247     Proc2  26 27  |  0  0 28  | 29
8248             0  0  | 31 32 33  |  0
8249 .ve
8250 
8251 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8252 @*/
8253 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8254 {
8255   PetscMPIInt size;
8256   Mat        *local;
8257   IS          iscoltmp;
8258   PetscBool   flg;
8259 
8260   PetscFunctionBegin;
8261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8262   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8263   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8264   PetscValidPointer(newmat, 5);
8265   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8266   PetscValidType(mat, 1);
8267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8268   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8269 
8270   MatCheckPreallocated(mat, 1);
8271   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8272 
8273   if (!iscol || isrow == iscol) {
8274     PetscBool   stride;
8275     PetscMPIInt grabentirematrix = 0, grab;
8276     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8277     if (stride) {
8278       PetscInt first, step, n, rstart, rend;
8279       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8280       if (step == 1) {
8281         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8282         if (rstart == first) {
8283           PetscCall(ISGetLocalSize(isrow, &n));
8284           if (n == rend - rstart) grabentirematrix = 1;
8285         }
8286       }
8287     }
8288     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8289     if (grab) {
8290       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8291       if (cll == MAT_INITIAL_MATRIX) {
8292         *newmat = mat;
8293         PetscCall(PetscObjectReference((PetscObject)mat));
8294       }
8295       PetscFunctionReturn(0);
8296     }
8297   }
8298 
8299   if (!iscol) {
8300     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8301   } else {
8302     iscoltmp = iscol;
8303   }
8304 
8305   /* if original matrix is on just one processor then use submatrix generated */
8306   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8307     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8308     goto setproperties;
8309   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8310     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8311     *newmat = *local;
8312     PetscCall(PetscFree(local));
8313     goto setproperties;
8314   } else if (!mat->ops->createsubmatrix) {
8315     /* Create a new matrix type that implements the operation using the full matrix */
8316     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8317     switch (cll) {
8318     case MAT_INITIAL_MATRIX:
8319       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8320       break;
8321     case MAT_REUSE_MATRIX:
8322       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8323       break;
8324     default:
8325       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8326     }
8327     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8328     goto setproperties;
8329   }
8330 
8331   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8332   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8333   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8334 
8335 setproperties:
8336   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8337   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8338   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8339   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8340   PetscFunctionReturn(0);
8341 }
8342 
8343 /*@
8344    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8345 
8346    Not Collective
8347 
8348    Input Parameters:
8349 +  A - the matrix we wish to propagate options from
8350 -  B - the matrix we wish to propagate options to
8351 
8352    Level: beginner
8353 
8354    Note:
8355    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8356 
8357 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8358 @*/
8359 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8360 {
8361   PetscFunctionBegin;
8362   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8363   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8364   B->symmetry_eternal            = A->symmetry_eternal;
8365   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8366   B->symmetric                   = A->symmetric;
8367   B->structurally_symmetric      = A->structurally_symmetric;
8368   B->spd                         = A->spd;
8369   B->hermitian                   = A->hermitian;
8370   PetscFunctionReturn(0);
8371 }
8372 
8373 /*@
8374    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8375    used during the assembly process to store values that belong to
8376    other processors.
8377 
8378    Not Collective
8379 
8380    Input Parameters:
8381 +  mat   - the matrix
8382 .  size  - the initial size of the stash.
8383 -  bsize - the initial size of the block-stash(if used).
8384 
8385    Options Database Keys:
8386 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8387 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8388 
8389    Level: intermediate
8390 
8391    Notes:
8392      The block-stash is used for values set with `MatSetValuesBlocked()` while
8393      the stash is used for values set with `MatSetValues()`
8394 
8395      Run with the option -info and look for output of the form
8396      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8397      to determine the appropriate value, MM, to use for size and
8398      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8399      to determine the value, BMM to use for bsize
8400 
8401 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8402 @*/
8403 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8404 {
8405   PetscFunctionBegin;
8406   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8407   PetscValidType(mat, 1);
8408   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8409   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8410   PetscFunctionReturn(0);
8411 }
8412 
8413 /*@
8414    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8415      the matrix
8416 
8417    Neighbor-wise Collective on mat
8418 
8419    Input Parameters:
8420 +  mat   - the matrix
8421 .  x,y - the vectors
8422 -  w - where the result is stored
8423 
8424    Level: intermediate
8425 
8426    Notes:
8427     w may be the same vector as y.
8428 
8429     This allows one to use either the restriction or interpolation (its transpose)
8430     matrix to do the interpolation
8431 
8432 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8433 @*/
8434 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8435 {
8436   PetscInt M, N, Ny;
8437 
8438   PetscFunctionBegin;
8439   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8440   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8441   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8442   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8443   PetscCall(MatGetSize(A, &M, &N));
8444   PetscCall(VecGetSize(y, &Ny));
8445   if (M == Ny) {
8446     PetscCall(MatMultAdd(A, x, y, w));
8447   } else {
8448     PetscCall(MatMultTransposeAdd(A, x, y, w));
8449   }
8450   PetscFunctionReturn(0);
8451 }
8452 
8453 /*@
8454    MatInterpolate - y = A*x or A'*x depending on the shape of
8455      the matrix
8456 
8457    Neighbor-wise Collective on mat
8458 
8459    Input Parameters:
8460 +  mat   - the matrix
8461 -  x,y - the vectors
8462 
8463    Level: intermediate
8464 
8465    Note:
8466     This allows one to use either the restriction or interpolation (its transpose)
8467     matrix to do the interpolation
8468 
8469 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8470 @*/
8471 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8472 {
8473   PetscInt M, N, Ny;
8474 
8475   PetscFunctionBegin;
8476   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8477   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8478   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8479   PetscCall(MatGetSize(A, &M, &N));
8480   PetscCall(VecGetSize(y, &Ny));
8481   if (M == Ny) {
8482     PetscCall(MatMult(A, x, y));
8483   } else {
8484     PetscCall(MatMultTranspose(A, x, y));
8485   }
8486   PetscFunctionReturn(0);
8487 }
8488 
8489 /*@
8490    MatRestrict - y = A*x or A'*x
8491 
8492    Neighbor-wise Collective on Mat
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 restriction
8503 
8504 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8505 @*/
8506 PetscErrorCode MatRestrict(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    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8526 
8527    Neighbor-wise Collective on Mat
8528 
8529    Input Parameters:
8530 +  mat   - the matrix
8531 -  w, x - the input dense matrices
8532 
8533    Output Parameters:
8534 .  y - the output dense matrix
8535 
8536    Level: intermediate
8537 
8538    Note:
8539     This allows one to use either the restriction or interpolation (its transpose)
8540     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8541     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8542 
8543 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8544 @*/
8545 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8546 {
8547   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8548   PetscBool trans = PETSC_TRUE;
8549   MatReuse  reuse = MAT_INITIAL_MATRIX;
8550 
8551   PetscFunctionBegin;
8552   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8553   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8554   PetscValidType(x, 2);
8555   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8556   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8557   PetscCall(MatGetSize(A, &M, &N));
8558   PetscCall(MatGetSize(x, &Mx, &Nx));
8559   if (N == Mx) trans = PETSC_FALSE;
8560   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);
8561   Mo = trans ? N : M;
8562   if (*y) {
8563     PetscCall(MatGetSize(*y, &My, &Ny));
8564     if (Mo == My && Nx == Ny) {
8565       reuse = MAT_REUSE_MATRIX;
8566     } else {
8567       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);
8568       PetscCall(MatDestroy(y));
8569     }
8570   }
8571 
8572   if (w && *y == w) { /* this is to minimize changes in PCMG */
8573     PetscBool flg;
8574 
8575     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8576     if (w) {
8577       PetscInt My, Ny, Mw, Nw;
8578 
8579       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8580       PetscCall(MatGetSize(*y, &My, &Ny));
8581       PetscCall(MatGetSize(w, &Mw, &Nw));
8582       if (!flg || My != Mw || Ny != Nw) w = NULL;
8583     }
8584     if (!w) {
8585       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8586       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8587       PetscCall(PetscObjectDereference((PetscObject)w));
8588     } else {
8589       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8590     }
8591   }
8592   if (!trans) {
8593     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8594   } else {
8595     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8596   }
8597   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8598   PetscFunctionReturn(0);
8599 }
8600 
8601 /*@
8602    MatMatInterpolate - Y = A*X or A'*X
8603 
8604    Neighbor-wise Collective on Mat
8605 
8606    Input Parameters:
8607 +  mat   - the matrix
8608 -  x - the input dense matrix
8609 
8610    Output Parameters:
8611 .  y - the output dense matrix
8612 
8613    Level: intermediate
8614 
8615    Note:
8616     This allows one to use either the restriction or interpolation (its transpose)
8617     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8618     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8619 
8620 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8621 @*/
8622 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8623 {
8624   PetscFunctionBegin;
8625   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8626   PetscFunctionReturn(0);
8627 }
8628 
8629 /*@
8630    MatMatRestrict - Y = A*X or A'*X
8631 
8632    Neighbor-wise Collective on Mat
8633 
8634    Input Parameters:
8635 +  mat   - the matrix
8636 -  x - the input dense matrix
8637 
8638    Output Parameters:
8639 .  y - the output dense matrix
8640 
8641    Level: intermediate
8642 
8643    Note:
8644     This allows one to use either the restriction or interpolation (its transpose)
8645     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8646     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8647 
8648 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8649 @*/
8650 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8651 {
8652   PetscFunctionBegin;
8653   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8654   PetscFunctionReturn(0);
8655 }
8656 
8657 /*@
8658    MatGetNullSpace - retrieves the null space of a matrix.
8659 
8660    Logically Collective on mat
8661 
8662    Input Parameters:
8663 +  mat - the matrix
8664 -  nullsp - the null space object
8665 
8666    Level: developer
8667 
8668 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8669 @*/
8670 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8671 {
8672   PetscFunctionBegin;
8673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8674   PetscValidPointer(nullsp, 2);
8675   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8676   PetscFunctionReturn(0);
8677 }
8678 
8679 /*@
8680    MatSetNullSpace - attaches a null space to a matrix.
8681 
8682    Logically Collective on mat
8683 
8684    Input Parameters:
8685 +  mat - the matrix
8686 -  nullsp - the null space object
8687 
8688    Level: advanced
8689 
8690    Notes:
8691       This null space is used by the `KSP` linear solvers to solve singular systems.
8692 
8693       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
8694 
8695       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
8696       to zero but the linear system will still be solved in a least squares sense.
8697 
8698       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8699    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).
8700    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
8701    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
8702    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).
8703    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8704 
8705     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8706     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8707     routine also automatically calls `MatSetTransposeNullSpace()`.
8708 
8709     The user should call `MatNullSpaceDestroy()`.
8710 
8711 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8712           `KSPSetPCSide()`
8713 @*/
8714 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8715 {
8716   PetscFunctionBegin;
8717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8718   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8719   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8720   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8721   mat->nullsp = nullsp;
8722   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8723   PetscFunctionReturn(0);
8724 }
8725 
8726 /*@
8727    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8728 
8729    Logically Collective on mat
8730 
8731    Input Parameters:
8732 +  mat - the matrix
8733 -  nullsp - the null space object
8734 
8735    Level: developer
8736 
8737 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8738 @*/
8739 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8740 {
8741   PetscFunctionBegin;
8742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8743   PetscValidType(mat, 1);
8744   PetscValidPointer(nullsp, 2);
8745   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8746   PetscFunctionReturn(0);
8747 }
8748 
8749 /*@
8750    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8751 
8752    Logically Collective on mat
8753 
8754    Input Parameters:
8755 +  mat - the matrix
8756 -  nullsp - the null space object
8757 
8758    Level: advanced
8759 
8760    Notes:
8761    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8762 
8763    See `MatSetNullSpace()`
8764 
8765 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8766 @*/
8767 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8768 {
8769   PetscFunctionBegin;
8770   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8771   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8772   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8773   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8774   mat->transnullsp = nullsp;
8775   PetscFunctionReturn(0);
8776 }
8777 
8778 /*@
8779    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8780         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8781 
8782    Logically Collective on mat
8783 
8784    Input Parameters:
8785 +  mat - the matrix
8786 -  nullsp - the null space object
8787 
8788    Level: advanced
8789 
8790    Notes:
8791    Overwrites any previous near null space that may have been attached
8792 
8793    You can remove the null space by calling this routine with an nullsp of NULL
8794 
8795 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8796 @*/
8797 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8798 {
8799   PetscFunctionBegin;
8800   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8801   PetscValidType(mat, 1);
8802   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8803   MatCheckPreallocated(mat, 1);
8804   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8805   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8806   mat->nearnullsp = nullsp;
8807   PetscFunctionReturn(0);
8808 }
8809 
8810 /*@
8811    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8812 
8813    Not Collective
8814 
8815    Input Parameter:
8816 .  mat - the matrix
8817 
8818    Output Parameter:
8819 .  nullsp - the null space object, NULL if not set
8820 
8821    Level: advanced
8822 
8823 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8824 @*/
8825 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8826 {
8827   PetscFunctionBegin;
8828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8829   PetscValidType(mat, 1);
8830   PetscValidPointer(nullsp, 2);
8831   MatCheckPreallocated(mat, 1);
8832   *nullsp = mat->nearnullsp;
8833   PetscFunctionReturn(0);
8834 }
8835 
8836 /*@C
8837    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8838 
8839    Collective on mat
8840 
8841    Input Parameters:
8842 +  mat - the matrix
8843 .  row - row/column permutation
8844 .  fill - expected fill factor >= 1.0
8845 -  level - level of fill, for ICC(k)
8846 
8847    Notes:
8848    Probably really in-place only when level of fill is zero, otherwise allocates
8849    new space to store factored matrix and deletes previous memory.
8850 
8851    Most users should employ the `KSP` interface for linear solvers
8852    instead of working directly with matrix algebra routines such as this.
8853    See, e.g., `KSPCreate()`.
8854 
8855    Level: developer
8856 
8857    Developer Note:
8858    The Fortran interface is not autogenerated as the f90
8859    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8860 
8861 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8862 @*/
8863 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8864 {
8865   PetscFunctionBegin;
8866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8867   PetscValidType(mat, 1);
8868   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8869   PetscValidPointer(info, 3);
8870   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8871   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8872   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8873   MatCheckPreallocated(mat, 1);
8874   PetscUseTypeMethod(mat, iccfactor, row, info);
8875   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8876   PetscFunctionReturn(0);
8877 }
8878 
8879 /*@
8880    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8881          ghosted ones.
8882 
8883    Not Collective
8884 
8885    Input Parameters:
8886 +  mat - the matrix
8887 -  diag - the diagonal values, including ghost ones
8888 
8889    Level: developer
8890 
8891    Notes:
8892     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8893 
8894     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8895 
8896 .seealso: `MatDiagonalScale()`
8897 @*/
8898 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8899 {
8900   PetscMPIInt size;
8901 
8902   PetscFunctionBegin;
8903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8904   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8905   PetscValidType(mat, 1);
8906 
8907   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8908   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8909   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8910   if (size == 1) {
8911     PetscInt n, m;
8912     PetscCall(VecGetSize(diag, &n));
8913     PetscCall(MatGetSize(mat, NULL, &m));
8914     if (m == n) {
8915       PetscCall(MatDiagonalScale(mat, NULL, diag));
8916     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8917   } else {
8918     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8919   }
8920   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8921   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8922   PetscFunctionReturn(0);
8923 }
8924 
8925 /*@
8926    MatGetInertia - Gets the inertia from a factored matrix
8927 
8928    Collective on mat
8929 
8930    Input Parameter:
8931 .  mat - the matrix
8932 
8933    Output Parameters:
8934 +   nneg - number of negative eigenvalues
8935 .   nzero - number of zero eigenvalues
8936 -   npos - number of positive eigenvalues
8937 
8938    Level: advanced
8939 
8940    Note:
8941     Matrix must have been factored by `MatCholeskyFactor()`
8942 
8943 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8944 @*/
8945 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8946 {
8947   PetscFunctionBegin;
8948   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8949   PetscValidType(mat, 1);
8950   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8951   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8952   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8953   PetscFunctionReturn(0);
8954 }
8955 
8956 /* ----------------------------------------------------------------*/
8957 /*@C
8958    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8959 
8960    Neighbor-wise Collective on mat
8961 
8962    Input Parameters:
8963 +  mat - the factored matrix obtained with `MatGetFactor()`
8964 -  b - the right-hand-side vectors
8965 
8966    Output Parameter:
8967 .  x - the result vectors
8968 
8969    Note:
8970    The vectors b and x cannot be the same.  I.e., one cannot
8971    call `MatSolves`(A,x,x).
8972 
8973    Level: developer
8974 
8975 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8976 @*/
8977 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
8978 {
8979   PetscFunctionBegin;
8980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8981   PetscValidType(mat, 1);
8982   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
8983   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8984   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8985 
8986   MatCheckPreallocated(mat, 1);
8987   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
8988   PetscUseTypeMethod(mat, solves, b, x);
8989   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
8990   PetscFunctionReturn(0);
8991 }
8992 
8993 /*@
8994    MatIsSymmetric - Test whether a matrix is symmetric
8995 
8996    Collective on mat
8997 
8998    Input Parameters:
8999 +  A - the matrix to test
9000 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9001 
9002    Output Parameters:
9003 .  flg - the result
9004 
9005    Notes:
9006     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9007 
9008     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9009 
9010     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9011     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9012 
9013    Level: intermediate
9014 
9015 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9016           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9017 @*/
9018 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9019 {
9020   PetscFunctionBegin;
9021   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9022   PetscValidBoolPointer(flg, 3);
9023 
9024   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9025   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9026   else {
9027     if (!A->ops->issymmetric) {
9028       MatType mattype;
9029       PetscCall(MatGetType(A, &mattype));
9030       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9031     }
9032     PetscUseTypeMethod(A, issymmetric, tol, flg);
9033     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9034   }
9035   PetscFunctionReturn(0);
9036 }
9037 
9038 /*@
9039    MatIsHermitian - Test whether a matrix is Hermitian
9040 
9041    Collective on Mat
9042 
9043    Input Parameters:
9044 +  A - the matrix to test
9045 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9046 
9047    Output Parameters:
9048 .  flg - the result
9049 
9050    Level: intermediate
9051 
9052    Notes:
9053     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9054 
9055     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9056 
9057     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9058     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9059 
9060 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9061           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9062 @*/
9063 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9064 {
9065   PetscFunctionBegin;
9066   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9067   PetscValidBoolPointer(flg, 3);
9068 
9069   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9070   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9071   else {
9072     if (!A->ops->ishermitian) {
9073       MatType mattype;
9074       PetscCall(MatGetType(A, &mattype));
9075       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9076     }
9077     PetscUseTypeMethod(A, ishermitian, tol, flg);
9078     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9079   }
9080   PetscFunctionReturn(0);
9081 }
9082 
9083 /*@
9084    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9085 
9086    Not Collective
9087 
9088    Input Parameter:
9089 .  A - the matrix to check
9090 
9091    Output Parameters:
9092 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9093 -  flg - the result (only valid if set is `PETSC_TRUE`)
9094 
9095    Level: advanced
9096 
9097    Notes:
9098    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9099    if you want it explicitly checked
9100 
9101     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9102     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9103 
9104 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9105 @*/
9106 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9107 {
9108   PetscFunctionBegin;
9109   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9110   PetscValidBoolPointer(set, 2);
9111   PetscValidBoolPointer(flg, 3);
9112   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9113     *set = PETSC_TRUE;
9114     *flg = PetscBool3ToBool(A->symmetric);
9115   } else {
9116     *set = PETSC_FALSE;
9117   }
9118   PetscFunctionReturn(0);
9119 }
9120 
9121 /*@
9122    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9123 
9124    Not Collective
9125 
9126    Input Parameter:
9127 .  A - the matrix to check
9128 
9129    Output Parameters:
9130 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9131 -  flg - the result (only valid if set is `PETSC_TRUE`)
9132 
9133    Level: advanced
9134 
9135    Notes:
9136    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9137 
9138    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9139    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9140 
9141 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9142 @*/
9143 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9144 {
9145   PetscFunctionBegin;
9146   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9147   PetscValidBoolPointer(set, 2);
9148   PetscValidBoolPointer(flg, 3);
9149   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9150     *set = PETSC_TRUE;
9151     *flg = PetscBool3ToBool(A->spd);
9152   } else {
9153     *set = PETSC_FALSE;
9154   }
9155   PetscFunctionReturn(0);
9156 }
9157 
9158 /*@
9159    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9160 
9161    Not Collective
9162 
9163    Input Parameter:
9164 .  A - the matrix to check
9165 
9166    Output Parameters:
9167 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9168 -  flg - the result (only valid if set is `PETSC_TRUE`)
9169 
9170    Level: advanced
9171 
9172    Notes:
9173    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9174    if you want it explicitly checked
9175 
9176    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9177    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9178 
9179 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9180 @*/
9181 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9182 {
9183   PetscFunctionBegin;
9184   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9185   PetscValidBoolPointer(set, 2);
9186   PetscValidBoolPointer(flg, 3);
9187   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9188     *set = PETSC_TRUE;
9189     *flg = PetscBool3ToBool(A->hermitian);
9190   } else {
9191     *set = PETSC_FALSE;
9192   }
9193   PetscFunctionReturn(0);
9194 }
9195 
9196 /*@
9197    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9198 
9199    Collective on Mat
9200 
9201    Input Parameter:
9202 .  A - the matrix to test
9203 
9204    Output Parameters:
9205 .  flg - the result
9206 
9207    Notes:
9208    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9209 
9210    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
9211    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9212 
9213    Level: intermediate
9214 
9215 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9216 @*/
9217 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9218 {
9219   PetscFunctionBegin;
9220   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9221   PetscValidBoolPointer(flg, 2);
9222   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9223     *flg = PetscBool3ToBool(A->structurally_symmetric);
9224   } else {
9225     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9226     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9227   }
9228   PetscFunctionReturn(0);
9229 }
9230 
9231 /*@
9232    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9233 
9234    Not Collective
9235 
9236    Input Parameter:
9237 .  A - the matrix to check
9238 
9239    Output Parameters:
9240 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9241 -  flg - the result (only valid if set is PETSC_TRUE)
9242 
9243    Level: advanced
9244 
9245    Notes:
9246    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
9247    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9248 
9249    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9250 
9251 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9252 @*/
9253 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9254 {
9255   PetscFunctionBegin;
9256   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9257   PetscValidBoolPointer(set, 2);
9258   PetscValidBoolPointer(flg, 3);
9259   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9260     *set = PETSC_TRUE;
9261     *flg = PetscBool3ToBool(A->structurally_symmetric);
9262   } else {
9263     *set = PETSC_FALSE;
9264   }
9265   PetscFunctionReturn(0);
9266 }
9267 
9268 /*@
9269    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9270        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9271 
9272     Not collective
9273 
9274    Input Parameter:
9275 .   mat - the matrix
9276 
9277    Output Parameters:
9278 +   nstash   - the size of the stash
9279 .   reallocs - the number of additional mallocs incurred.
9280 .   bnstash   - the size of the block stash
9281 -   breallocs - the number of additional mallocs incurred.in the block stash
9282 
9283    Level: advanced
9284 
9285 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9286 @*/
9287 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9288 {
9289   PetscFunctionBegin;
9290   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9291   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9292   PetscFunctionReturn(0);
9293 }
9294 
9295 /*@C
9296    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9297    parallel layout, `PetscLayout` for rows and columns
9298 
9299    Collective on mat
9300 
9301    Input Parameter:
9302 .  mat - the matrix
9303 
9304    Output Parameters:
9305 +   right - (optional) vector that the matrix can be multiplied against
9306 -   left - (optional) vector that the matrix vector product can be stored in
9307 
9308    Notes:
9309     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()`.
9310 
9311     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9312 
9313   Level: advanced
9314 
9315 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9316 @*/
9317 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9318 {
9319   PetscFunctionBegin;
9320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9321   PetscValidType(mat, 1);
9322   if (mat->ops->getvecs) {
9323     PetscUseTypeMethod(mat, getvecs, right, left);
9324   } else {
9325     PetscInt rbs, cbs;
9326     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9327     if (right) {
9328       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9329       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9330       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9331       PetscCall(VecSetBlockSize(*right, cbs));
9332       PetscCall(VecSetType(*right, mat->defaultvectype));
9333 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9334       if (mat->boundtocpu && mat->bindingpropagates) {
9335         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9336         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9337       }
9338 #endif
9339       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9340     }
9341     if (left) {
9342       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9343       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9344       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9345       PetscCall(VecSetBlockSize(*left, rbs));
9346       PetscCall(VecSetType(*left, mat->defaultvectype));
9347 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9348       if (mat->boundtocpu && mat->bindingpropagates) {
9349         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9350         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9351       }
9352 #endif
9353       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9354     }
9355   }
9356   PetscFunctionReturn(0);
9357 }
9358 
9359 /*@C
9360    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9361      with default values.
9362 
9363    Not Collective
9364 
9365    Input Parameters:
9366 .    info - the `MatFactorInfo` data structure
9367 
9368    Notes:
9369     The solvers are generally used through the `KSP` and `PC` objects, for example
9370           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9371 
9372     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9373 
9374    Level: developer
9375 
9376    Developer Note:
9377    The Fortran interface is not autogenerated as the f90
9378    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9379 
9380 .seealso: `MatGetFactor()`, `MatFactorInfo`
9381 @*/
9382 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9383 {
9384   PetscFunctionBegin;
9385   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9386   PetscFunctionReturn(0);
9387 }
9388 
9389 /*@
9390    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9391 
9392    Collective on mat
9393 
9394    Input Parameters:
9395 +  mat - the factored matrix
9396 -  is - the index set defining the Schur indices (0-based)
9397 
9398    Notes:
9399     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9400 
9401    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9402 
9403    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9404 
9405    Level: advanced
9406 
9407 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9408           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9409 
9410 @*/
9411 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9412 {
9413   PetscErrorCode (*f)(Mat, IS);
9414 
9415   PetscFunctionBegin;
9416   PetscValidType(mat, 1);
9417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9418   PetscValidType(is, 2);
9419   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9420   PetscCheckSameComm(mat, 1, is, 2);
9421   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9422   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9423   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9424   PetscCall(MatDestroy(&mat->schur));
9425   PetscCall((*f)(mat, is));
9426   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9427   PetscFunctionReturn(0);
9428 }
9429 
9430 /*@
9431   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9432 
9433    Logically Collective on mat
9434 
9435    Input Parameters:
9436 +  F - the factored matrix obtained by calling `MatGetFactor()`
9437 .  S - location where to return the Schur complement, can be NULL
9438 -  status - the status of the Schur complement matrix, can be NULL
9439 
9440    Notes:
9441    You must call `MatFactorSetSchurIS()` before calling this routine.
9442 
9443    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9444 
9445    The routine provides a copy of the Schur matrix stored within the solver data structures.
9446    The caller must destroy the object when it is no longer needed.
9447    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9448 
9449    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)
9450 
9451    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9452 
9453    Developer Note:
9454     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9455    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9456 
9457    Level: advanced
9458 
9459 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9460 @*/
9461 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9462 {
9463   PetscFunctionBegin;
9464   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9465   if (S) PetscValidPointer(S, 2);
9466   if (status) PetscValidPointer(status, 3);
9467   if (S) {
9468     PetscErrorCode (*f)(Mat, Mat *);
9469 
9470     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9471     if (f) {
9472       PetscCall((*f)(F, S));
9473     } else {
9474       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9475     }
9476   }
9477   if (status) *status = F->schur_status;
9478   PetscFunctionReturn(0);
9479 }
9480 
9481 /*@
9482   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9483 
9484    Logically Collective on mat
9485 
9486    Input Parameters:
9487 +  F - the factored matrix obtained by calling `MatGetFactor()`
9488 .  *S - location where to return the Schur complement, can be NULL
9489 -  status - the status of the Schur complement matrix, can be NULL
9490 
9491    Notes:
9492    You must call `MatFactorSetSchurIS()` before calling this routine.
9493 
9494    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9495 
9496    The routine returns a the Schur Complement stored within the data strutures of the solver.
9497 
9498    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9499 
9500    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9501 
9502    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9503 
9504    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9505 
9506    Level: advanced
9507 
9508 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9509 @*/
9510 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9511 {
9512   PetscFunctionBegin;
9513   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9514   if (S) PetscValidPointer(S, 2);
9515   if (status) PetscValidPointer(status, 3);
9516   if (S) *S = F->schur;
9517   if (status) *status = F->schur_status;
9518   PetscFunctionReturn(0);
9519 }
9520 
9521 /*@
9522   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9523 
9524    Logically Collective on mat
9525 
9526    Input Parameters:
9527 +  F - the factored matrix obtained by calling `MatGetFactor()`
9528 .  *S - location where the Schur complement is stored
9529 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9530 
9531    Level: advanced
9532 
9533 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9534 @*/
9535 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9536 {
9537   PetscFunctionBegin;
9538   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9539   if (S) {
9540     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9541     *S = NULL;
9542   }
9543   F->schur_status = status;
9544   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9545   PetscFunctionReturn(0);
9546 }
9547 
9548 /*@
9549   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9550 
9551    Logically Collective on mat
9552 
9553    Input Parameters:
9554 +  F - the factored matrix obtained by calling `MatGetFactor()`
9555 .  rhs - location where the right hand side of the Schur complement system is stored
9556 -  sol - location where the solution of the Schur complement system has to be returned
9557 
9558    Notes:
9559    The sizes of the vectors should match the size of the Schur complement
9560 
9561    Must be called after `MatFactorSetSchurIS()`
9562 
9563    Level: advanced
9564 
9565 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9566 @*/
9567 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9568 {
9569   PetscFunctionBegin;
9570   PetscValidType(F, 1);
9571   PetscValidType(rhs, 2);
9572   PetscValidType(sol, 3);
9573   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9574   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9575   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9576   PetscCheckSameComm(F, 1, rhs, 2);
9577   PetscCheckSameComm(F, 1, sol, 3);
9578   PetscCall(MatFactorFactorizeSchurComplement(F));
9579   switch (F->schur_status) {
9580   case MAT_FACTOR_SCHUR_FACTORED:
9581     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9582     break;
9583   case MAT_FACTOR_SCHUR_INVERTED:
9584     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9585     break;
9586   default:
9587     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9588   }
9589   PetscFunctionReturn(0);
9590 }
9591 
9592 /*@
9593   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9594 
9595    Logically Collective on mat
9596 
9597    Input Parameters:
9598 +  F - the factored matrix obtained by calling `MatGetFactor()`
9599 .  rhs - location where the right hand side of the Schur complement system is stored
9600 -  sol - location where the solution of the Schur complement system has to be returned
9601 
9602    Notes:
9603    The sizes of the vectors should match the size of the Schur complement
9604 
9605    Must be called after `MatFactorSetSchurIS()`
9606 
9607    Level: advanced
9608 
9609 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9610 @*/
9611 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9612 {
9613   PetscFunctionBegin;
9614   PetscValidType(F, 1);
9615   PetscValidType(rhs, 2);
9616   PetscValidType(sol, 3);
9617   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9618   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9619   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9620   PetscCheckSameComm(F, 1, rhs, 2);
9621   PetscCheckSameComm(F, 1, sol, 3);
9622   PetscCall(MatFactorFactorizeSchurComplement(F));
9623   switch (F->schur_status) {
9624   case MAT_FACTOR_SCHUR_FACTORED:
9625     PetscCall(MatSolve(F->schur, rhs, sol));
9626     break;
9627   case MAT_FACTOR_SCHUR_INVERTED:
9628     PetscCall(MatMult(F->schur, rhs, sol));
9629     break;
9630   default:
9631     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9632   }
9633   PetscFunctionReturn(0);
9634 }
9635 
9636 /*@
9637   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9638 
9639    Logically Collective on F
9640 
9641    Input Parameters:
9642 .  F - the factored matrix obtained by calling `MatGetFactor()`
9643 
9644    Notes:
9645     Must be called after `MatFactorSetSchurIS()`.
9646 
9647    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9648 
9649    Level: advanced
9650 
9651 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9652 @*/
9653 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9654 {
9655   PetscFunctionBegin;
9656   PetscValidType(F, 1);
9657   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9658   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9659   PetscCall(MatFactorFactorizeSchurComplement(F));
9660   PetscCall(MatFactorInvertSchurComplement_Private(F));
9661   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9662   PetscFunctionReturn(0);
9663 }
9664 
9665 /*@
9666   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9667 
9668    Logically Collective on mat
9669 
9670    Input Parameters:
9671 .  F - the factored matrix obtained by calling `MatGetFactor()`
9672 
9673    Note:
9674     Must be called after `MatFactorSetSchurIS()`
9675 
9676    Level: advanced
9677 
9678 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9679 @*/
9680 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9681 {
9682   PetscFunctionBegin;
9683   PetscValidType(F, 1);
9684   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9685   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9686   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9687   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9688   PetscFunctionReturn(0);
9689 }
9690 
9691 /*@
9692    MatPtAP - Creates the matrix product C = P^T * A * P
9693 
9694    Neighbor-wise Collective on A
9695 
9696    Input Parameters:
9697 +  A - the matrix
9698 .  P - the projection matrix
9699 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9700 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9701           if the result is a dense matrix this is irrelevant
9702 
9703    Output Parameters:
9704 .  C - the product matrix
9705 
9706    Notes:
9707    C will be created and must be destroyed by the user with `MatDestroy()`.
9708 
9709    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9710 
9711    Developer Note:
9712    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9713 
9714    Level: intermediate
9715 
9716 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9717 @*/
9718 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9719 {
9720   PetscFunctionBegin;
9721   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9722   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9723 
9724   if (scall == MAT_INITIAL_MATRIX) {
9725     PetscCall(MatProductCreate(A, P, NULL, C));
9726     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9727     PetscCall(MatProductSetAlgorithm(*C, "default"));
9728     PetscCall(MatProductSetFill(*C, fill));
9729 
9730     (*C)->product->api_user = PETSC_TRUE;
9731     PetscCall(MatProductSetFromOptions(*C));
9732     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);
9733     PetscCall(MatProductSymbolic(*C));
9734   } else { /* scall == MAT_REUSE_MATRIX */
9735     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9736   }
9737 
9738   PetscCall(MatProductNumeric(*C));
9739   (*C)->symmetric = A->symmetric;
9740   (*C)->spd       = A->spd;
9741   PetscFunctionReturn(0);
9742 }
9743 
9744 /*@
9745    MatRARt - Creates the matrix product C = R * A * R^T
9746 
9747    Neighbor-wise Collective on A
9748 
9749    Input Parameters:
9750 +  A - the matrix
9751 .  R - the projection matrix
9752 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9753 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9754           if the result is a dense matrix this is irrelevant
9755 
9756    Output Parameters:
9757 .  C - the product matrix
9758 
9759    Notes:
9760    C will be created and must be destroyed by the user with `MatDestroy()`.
9761 
9762    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9763 
9764    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9765    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9766    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9767    We recommend using MatPtAP().
9768 
9769    Level: intermediate
9770 
9771 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9772 @*/
9773 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9774 {
9775   PetscFunctionBegin;
9776   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9777   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9778 
9779   if (scall == MAT_INITIAL_MATRIX) {
9780     PetscCall(MatProductCreate(A, R, NULL, C));
9781     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9782     PetscCall(MatProductSetAlgorithm(*C, "default"));
9783     PetscCall(MatProductSetFill(*C, fill));
9784 
9785     (*C)->product->api_user = PETSC_TRUE;
9786     PetscCall(MatProductSetFromOptions(*C));
9787     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);
9788     PetscCall(MatProductSymbolic(*C));
9789   } else { /* scall == MAT_REUSE_MATRIX */
9790     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9791   }
9792 
9793   PetscCall(MatProductNumeric(*C));
9794   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9795   PetscFunctionReturn(0);
9796 }
9797 
9798 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9799 {
9800   PetscFunctionBegin;
9801   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9802 
9803   if (scall == MAT_INITIAL_MATRIX) {
9804     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9805     PetscCall(MatProductCreate(A, B, NULL, C));
9806     PetscCall(MatProductSetType(*C, ptype));
9807     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9808     PetscCall(MatProductSetFill(*C, fill));
9809 
9810     (*C)->product->api_user = PETSC_TRUE;
9811     PetscCall(MatProductSetFromOptions(*C));
9812     PetscCall(MatProductSymbolic(*C));
9813   } else { /* scall == MAT_REUSE_MATRIX */
9814     Mat_Product *product = (*C)->product;
9815     PetscBool    isdense;
9816 
9817     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9818     if (isdense && product && product->type != ptype) {
9819       PetscCall(MatProductClear(*C));
9820       product = NULL;
9821     }
9822     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9823     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9824       if (isdense) {
9825         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9826         product           = (*C)->product;
9827         product->fill     = fill;
9828         product->api_user = PETSC_TRUE;
9829         product->clear    = PETSC_TRUE;
9830 
9831         PetscCall(MatProductSetType(*C, ptype));
9832         PetscCall(MatProductSetFromOptions(*C));
9833         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);
9834         PetscCall(MatProductSymbolic(*C));
9835       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9836     } else { /* user may change input matrices A or B when REUSE */
9837       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9838     }
9839   }
9840   PetscCall(MatProductNumeric(*C));
9841   PetscFunctionReturn(0);
9842 }
9843 
9844 /*@
9845    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9846 
9847    Neighbor-wise Collective on A
9848 
9849    Input Parameters:
9850 +  A - the left matrix
9851 .  B - the right matrix
9852 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9853 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9854           if the result is a dense matrix this is irrelevant
9855 
9856    Output Parameters:
9857 .  C - the product matrix
9858 
9859    Notes:
9860    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9861 
9862    `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
9863    call to this function with `MAT_INITIAL_MATRIX`.
9864 
9865    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9866 
9867    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`,
9868    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9869 
9870    Example of Usage:
9871 .vb
9872      MatProductCreate(A,B,NULL,&C);
9873      MatProductSetType(C,MATPRODUCT_AB);
9874      MatProductSymbolic(C);
9875      MatProductNumeric(C); // compute C=A * B
9876      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9877      MatProductNumeric(C);
9878      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9879      MatProductNumeric(C);
9880 .ve
9881 
9882    Level: intermediate
9883 
9884 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9885 @*/
9886 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9887 {
9888   PetscFunctionBegin;
9889   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9890   PetscFunctionReturn(0);
9891 }
9892 
9893 /*@
9894    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9895 
9896    Neighbor-wise Collective on A
9897 
9898    Input Parameters:
9899 +  A - the left matrix
9900 .  B - the right matrix
9901 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9902 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9903 
9904    Output Parameters:
9905 .  C - the product matrix
9906 
9907    Notes:
9908    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9909 
9910    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9911 
9912    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9913    actually needed.
9914 
9915    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9916    and for pairs of `MATMPIDENSE` matrices.
9917 
9918    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9919 
9920    Options Database Keys:
9921 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9922               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9923               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9924 
9925    Level: intermediate
9926 
9927 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9928 @*/
9929 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9930 {
9931   PetscFunctionBegin;
9932   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9933   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9934   PetscFunctionReturn(0);
9935 }
9936 
9937 /*@
9938    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9939 
9940    Neighbor-wise Collective on A
9941 
9942    Input Parameters:
9943 +  A - the left matrix
9944 .  B - the right matrix
9945 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9946 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9947 
9948    Output Parameters:
9949 .  C - the product matrix
9950 
9951    Notes:
9952    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9953 
9954    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9955 
9956    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9957 
9958    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9959    actually needed.
9960 
9961    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9962    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
9963 
9964    Level: intermediate
9965 
9966 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9967 @*/
9968 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9969 {
9970   PetscFunctionBegin;
9971   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
9972   PetscFunctionReturn(0);
9973 }
9974 
9975 /*@
9976    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9977 
9978    Neighbor-wise Collective on A
9979 
9980    Input Parameters:
9981 +  A - the left matrix
9982 .  B - the middle matrix
9983 .  C - the right matrix
9984 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9985 -  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
9986           if the result is a dense matrix this is irrelevant
9987 
9988    Output Parameters:
9989 .  D - the product matrix
9990 
9991    Notes:
9992    Unless scall is `MAT_REUSE_MATRIX` D will be created.
9993 
9994    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9995 
9996    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9997 
9998    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9999    actually needed.
10000 
10001    If you have many matrices with the same non-zero structure to multiply, you
10002    should use `MAT_REUSE_MATRIX` in all calls but the first
10003 
10004    Level: intermediate
10005 
10006 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10007 @*/
10008 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10009 {
10010   PetscFunctionBegin;
10011   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10012   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10013 
10014   if (scall == MAT_INITIAL_MATRIX) {
10015     PetscCall(MatProductCreate(A, B, C, D));
10016     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10017     PetscCall(MatProductSetAlgorithm(*D, "default"));
10018     PetscCall(MatProductSetFill(*D, fill));
10019 
10020     (*D)->product->api_user = PETSC_TRUE;
10021     PetscCall(MatProductSetFromOptions(*D));
10022     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,
10023                ((PetscObject)C)->type_name);
10024     PetscCall(MatProductSymbolic(*D));
10025   } else { /* user may change input matrices when REUSE */
10026     PetscCall(MatProductReplaceMats(A, B, C, *D));
10027   }
10028   PetscCall(MatProductNumeric(*D));
10029   PetscFunctionReturn(0);
10030 }
10031 
10032 /*@
10033    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10034 
10035    Collective on mat
10036 
10037    Input Parameters:
10038 +  mat - the matrix
10039 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10040 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10041 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10042 
10043    Output Parameter:
10044 .  matredundant - redundant matrix
10045 
10046    Notes:
10047    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10048    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10049 
10050    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10051    calling it.
10052 
10053    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10054 
10055    Level: advanced
10056 
10057 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10058 @*/
10059 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10060 {
10061   MPI_Comm       comm;
10062   PetscMPIInt    size;
10063   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10064   Mat_Redundant *redund     = NULL;
10065   PetscSubcomm   psubcomm   = NULL;
10066   MPI_Comm       subcomm_in = subcomm;
10067   Mat           *matseq;
10068   IS             isrow, iscol;
10069   PetscBool      newsubcomm = PETSC_FALSE;
10070 
10071   PetscFunctionBegin;
10072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10073   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10074     PetscValidPointer(*matredundant, 5);
10075     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10076   }
10077 
10078   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10079   if (size == 1 || nsubcomm == 1) {
10080     if (reuse == MAT_INITIAL_MATRIX) {
10081       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10082     } else {
10083       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");
10084       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10085     }
10086     PetscFunctionReturn(0);
10087   }
10088 
10089   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10090   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10091   MatCheckPreallocated(mat, 1);
10092 
10093   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10094   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10095     /* create psubcomm, then get subcomm */
10096     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10097     PetscCallMPI(MPI_Comm_size(comm, &size));
10098     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10099 
10100     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10101     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10102     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10103     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10104     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10105     newsubcomm = PETSC_TRUE;
10106     PetscCall(PetscSubcommDestroy(&psubcomm));
10107   }
10108 
10109   /* get isrow, iscol and a local sequential matrix matseq[0] */
10110   if (reuse == MAT_INITIAL_MATRIX) {
10111     mloc_sub = PETSC_DECIDE;
10112     nloc_sub = PETSC_DECIDE;
10113     if (bs < 1) {
10114       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10115       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10116     } else {
10117       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10118       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10119     }
10120     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10121     rstart = rend - mloc_sub;
10122     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10123     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10124   } else { /* reuse == MAT_REUSE_MATRIX */
10125     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");
10126     /* retrieve subcomm */
10127     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10128     redund = (*matredundant)->redundant;
10129     isrow  = redund->isrow;
10130     iscol  = redund->iscol;
10131     matseq = redund->matseq;
10132   }
10133   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10134 
10135   /* get matredundant over subcomm */
10136   if (reuse == MAT_INITIAL_MATRIX) {
10137     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10138 
10139     /* create a supporting struct and attach it to C for reuse */
10140     PetscCall(PetscNew(&redund));
10141     (*matredundant)->redundant = redund;
10142     redund->isrow              = isrow;
10143     redund->iscol              = iscol;
10144     redund->matseq             = matseq;
10145     if (newsubcomm) {
10146       redund->subcomm = subcomm;
10147     } else {
10148       redund->subcomm = MPI_COMM_NULL;
10149     }
10150   } else {
10151     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10152   }
10153 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
10154   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10155     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10156     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10157   }
10158 #endif
10159   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10160   PetscFunctionReturn(0);
10161 }
10162 
10163 /*@C
10164    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10165    a given `Mat`. Each submatrix can span multiple procs.
10166 
10167    Collective on mat
10168 
10169    Input Parameters:
10170 +  mat - the matrix
10171 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
10172 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10173 
10174    Output Parameter:
10175 .  subMat - 'parallel submatrices each spans a given subcomm
10176 
10177   Notes:
10178   The submatrix partition across processors is dictated by 'subComm' a
10179   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
10180   is not restriced to be grouped with consecutive original ranks.
10181 
10182   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10183   map directly to the layout of the original matrix [wrt the local
10184   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10185   into the 'DiagonalMat' of the subMat, hence it is used directly from
10186   the subMat. However the offDiagMat looses some columns - and this is
10187   reconstructed with `MatSetValues()`
10188 
10189   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10190 
10191   Level: advanced
10192 
10193 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10194 @*/
10195 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10196 {
10197   PetscMPIInt commsize, subCommSize;
10198 
10199   PetscFunctionBegin;
10200   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10201   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10202   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10203 
10204   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");
10205   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10206   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10207   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10208   PetscFunctionReturn(0);
10209 }
10210 
10211 /*@
10212    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10213 
10214    Not Collective
10215 
10216    Input Parameters:
10217 +  mat - matrix to extract local submatrix from
10218 .  isrow - local row indices for submatrix
10219 -  iscol - local column indices for submatrix
10220 
10221    Output Parameter:
10222 .  submat - the submatrix
10223 
10224    Level: intermediate
10225 
10226    Notes:
10227    The submat should be returned with `MatRestoreLocalSubMatrix()`.
10228 
10229    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10230    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10231 
10232    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10233    `MatSetValuesBlockedLocal()` will also be implemented.
10234 
10235    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10236    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10237 
10238 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10239 @*/
10240 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10241 {
10242   PetscFunctionBegin;
10243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10244   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10245   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10246   PetscCheckSameComm(isrow, 2, iscol, 3);
10247   PetscValidPointer(submat, 4);
10248   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10249 
10250   if (mat->ops->getlocalsubmatrix) {
10251     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10252   } else {
10253     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10254   }
10255   PetscFunctionReturn(0);
10256 }
10257 
10258 /*@
10259    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10260 
10261    Not Collective
10262 
10263    Input Parameters:
10264 +  mat - matrix to extract local submatrix from
10265 .  isrow - local row indices for submatrix
10266 .  iscol - local column indices for submatrix
10267 -  submat - the submatrix
10268 
10269    Level: intermediate
10270 
10271 .seealso: `MatGetLocalSubMatrix()`
10272 @*/
10273 PetscErrorCode MatRestoreLocalSubMatrix(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   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10282 
10283   if (mat->ops->restorelocalsubmatrix) {
10284     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10285   } else {
10286     PetscCall(MatDestroy(submat));
10287   }
10288   *submat = NULL;
10289   PetscFunctionReturn(0);
10290 }
10291 
10292 /* --------------------------------------------------------*/
10293 /*@
10294    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10295 
10296    Collective on mat
10297 
10298    Input Parameter:
10299 .  mat - the matrix
10300 
10301    Output Parameter:
10302 .  is - if any rows have zero diagonals this contains the list of them
10303 
10304    Level: developer
10305 
10306 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10307 @*/
10308 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10309 {
10310   PetscFunctionBegin;
10311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10312   PetscValidType(mat, 1);
10313   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10314   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10315 
10316   if (!mat->ops->findzerodiagonals) {
10317     Vec                diag;
10318     const PetscScalar *a;
10319     PetscInt          *rows;
10320     PetscInt           rStart, rEnd, r, nrow = 0;
10321 
10322     PetscCall(MatCreateVecs(mat, &diag, NULL));
10323     PetscCall(MatGetDiagonal(mat, diag));
10324     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10325     PetscCall(VecGetArrayRead(diag, &a));
10326     for (r = 0; r < rEnd - rStart; ++r)
10327       if (a[r] == 0.0) ++nrow;
10328     PetscCall(PetscMalloc1(nrow, &rows));
10329     nrow = 0;
10330     for (r = 0; r < rEnd - rStart; ++r)
10331       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10332     PetscCall(VecRestoreArrayRead(diag, &a));
10333     PetscCall(VecDestroy(&diag));
10334     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10335   } else {
10336     PetscUseTypeMethod(mat, findzerodiagonals, is);
10337   }
10338   PetscFunctionReturn(0);
10339 }
10340 
10341 /*@
10342    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10343 
10344    Collective on mat
10345 
10346    Input Parameter:
10347 .  mat - the matrix
10348 
10349    Output Parameter:
10350 .  is - contains the list of rows with off block diagonal entries
10351 
10352    Level: developer
10353 
10354 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10355 @*/
10356 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10357 {
10358   PetscFunctionBegin;
10359   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10360   PetscValidType(mat, 1);
10361   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10362   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10363 
10364   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10365   PetscFunctionReturn(0);
10366 }
10367 
10368 /*@C
10369   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10370 
10371   Collective on mat
10372 
10373   Input Parameters:
10374 . mat - the matrix
10375 
10376   Output Parameters:
10377 . values - the block inverses in column major order (FORTRAN-like)
10378 
10379    Notes:
10380    The size of the blocks is determined by the block size of the matrix.
10381 
10382    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10383 
10384    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10385 
10386    Fortran Note:
10387      This routine is not available from Fortran.
10388 
10389   Level: advanced
10390 
10391 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10392 @*/
10393 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10394 {
10395   PetscFunctionBegin;
10396   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10397   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10398   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10399   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10400   PetscFunctionReturn(0);
10401 }
10402 
10403 /*@C
10404   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10405 
10406   Collective on mat
10407 
10408   Input Parameters:
10409 + mat - the matrix
10410 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10411 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10412 
10413   Output Parameters:
10414 . values - the block inverses in column major order (FORTRAN-like)
10415 
10416   Notes:
10417   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10418 
10419   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10420 
10421   Fortran Note:
10422   This routine is not available from Fortran.
10423 
10424   Level: advanced
10425 
10426 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10427 @*/
10428 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10429 {
10430   PetscFunctionBegin;
10431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10432   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10433   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10434   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10435   PetscFunctionReturn(0);
10436 }
10437 
10438 /*@
10439   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10440 
10441   Collective on Mat
10442 
10443   Input Parameters:
10444 + A - the matrix
10445 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10446 
10447   Note:
10448   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10449 
10450   Level: advanced
10451 
10452 .seealso: `MatInvertBlockDiagonal()`
10453 @*/
10454 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10455 {
10456   const PetscScalar *vals;
10457   PetscInt          *dnnz;
10458   PetscInt           m, rstart, rend, bs, i, j;
10459 
10460   PetscFunctionBegin;
10461   PetscCall(MatInvertBlockDiagonal(A, &vals));
10462   PetscCall(MatGetBlockSize(A, &bs));
10463   PetscCall(MatGetLocalSize(A, &m, NULL));
10464   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10465   PetscCall(PetscMalloc1(m / bs, &dnnz));
10466   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10467   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10468   PetscCall(PetscFree(dnnz));
10469   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10470   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10471   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10472   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10473   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10474   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10475   PetscFunctionReturn(0);
10476 }
10477 
10478 /*@C
10479     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10480     via `MatTransposeColoringCreate()`.
10481 
10482     Collective on c
10483 
10484     Input Parameter:
10485 .   c - coloring context
10486 
10487     Level: intermediate
10488 
10489 .seealso: `MatTransposeColoringCreate()`
10490 @*/
10491 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10492 {
10493   MatTransposeColoring matcolor = *c;
10494 
10495   PetscFunctionBegin;
10496   if (!matcolor) PetscFunctionReturn(0);
10497   if (--((PetscObject)matcolor)->refct > 0) {
10498     matcolor = NULL;
10499     PetscFunctionReturn(0);
10500   }
10501 
10502   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10503   PetscCall(PetscFree(matcolor->rows));
10504   PetscCall(PetscFree(matcolor->den2sp));
10505   PetscCall(PetscFree(matcolor->colorforcol));
10506   PetscCall(PetscFree(matcolor->columns));
10507   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10508   PetscCall(PetscHeaderDestroy(c));
10509   PetscFunctionReturn(0);
10510 }
10511 
10512 /*@C
10513     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10514     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10515     `MatTransposeColoring` to sparse B.
10516 
10517     Collective on coloring
10518 
10519     Input Parameters:
10520 +   B - sparse matrix B
10521 .   Btdense - symbolic dense matrix B^T
10522 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10523 
10524     Output Parameter:
10525 .   Btdense - dense matrix B^T
10526 
10527     Level: developer
10528 
10529     Note:
10530     These are used internally for some implementations of `MatRARt()`
10531 
10532 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10533 
10534 @*/
10535 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10536 {
10537   PetscFunctionBegin;
10538   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10539   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10540   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10541 
10542   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10543   PetscFunctionReturn(0);
10544 }
10545 
10546 /*@C
10547     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10548     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10549     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10550     Csp from Cden.
10551 
10552     Collective on matcoloring
10553 
10554     Input Parameters:
10555 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10556 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10557 
10558     Output Parameter:
10559 .   Csp - sparse matrix
10560 
10561     Level: developer
10562 
10563     Note:
10564     These are used internally for some implementations of `MatRARt()`
10565 
10566 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10567 
10568 @*/
10569 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10570 {
10571   PetscFunctionBegin;
10572   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10573   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10574   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10575 
10576   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10577   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10578   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10579   PetscFunctionReturn(0);
10580 }
10581 
10582 /*@C
10583    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10584 
10585    Collective on mat
10586 
10587    Input Parameters:
10588 +  mat - the matrix product C
10589 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10590 
10591     Output Parameter:
10592 .   color - the new coloring context
10593 
10594     Level: intermediate
10595 
10596 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10597           `MatTransColoringApplyDenToSp()`
10598 @*/
10599 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10600 {
10601   MatTransposeColoring c;
10602   MPI_Comm             comm;
10603 
10604   PetscFunctionBegin;
10605   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10606   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10607   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10608 
10609   c->ctype = iscoloring->ctype;
10610   if (mat->ops->transposecoloringcreate) {
10611     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10612   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10613 
10614   *color = c;
10615   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10616   PetscFunctionReturn(0);
10617 }
10618 
10619 /*@
10620       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10621         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10622         same, otherwise it will be larger
10623 
10624      Not Collective
10625 
10626   Input Parameter:
10627 .    A  - the matrix
10628 
10629   Output Parameter:
10630 .    state - the current state
10631 
10632   Notes:
10633     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10634          different matrices
10635 
10636     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10637 
10638     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10639 
10640   Level: intermediate
10641 
10642 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10643 @*/
10644 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10645 {
10646   PetscFunctionBegin;
10647   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10648   *state = mat->nonzerostate;
10649   PetscFunctionReturn(0);
10650 }
10651 
10652 /*@
10653       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10654                  matrices from each processor
10655 
10656     Collective
10657 
10658    Input Parameters:
10659 +    comm - the communicators the parallel matrix will live on
10660 .    seqmat - the input sequential matrices
10661 .    n - number of local columns (or `PETSC_DECIDE`)
10662 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10663 
10664    Output Parameter:
10665 .    mpimat - the parallel matrix generated
10666 
10667     Level: developer
10668 
10669    Note:
10670     The number of columns of the matrix in EACH processor MUST be the same.
10671 
10672 .seealso: `Mat`
10673 @*/
10674 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10675 {
10676   PetscMPIInt size;
10677 
10678   PetscFunctionBegin;
10679   PetscCallMPI(MPI_Comm_size(comm, &size));
10680   if (size == 1) {
10681     if (reuse == MAT_INITIAL_MATRIX) {
10682       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10683     } else {
10684       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10685     }
10686     PetscFunctionReturn(0);
10687   }
10688 
10689   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");
10690 
10691   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10692   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10693   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10694   PetscFunctionReturn(0);
10695 }
10696 
10697 /*@
10698      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10699 
10700     Collective on A
10701 
10702    Input Parameters:
10703 +    A   - the matrix to create subdomains from
10704 -    N   - requested number of subdomains
10705 
10706    Output Parameters:
10707 +    n   - number of subdomains resulting on this rank
10708 -    iss - `IS` list with indices of subdomains on this rank
10709 
10710     Level: advanced
10711 
10712     Note:
10713     The number of subdomains must be smaller than the communicator size
10714 
10715 .seealso: `Mat`, `IS`
10716 @*/
10717 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10718 {
10719   MPI_Comm    comm, subcomm;
10720   PetscMPIInt size, rank, color;
10721   PetscInt    rstart, rend, k;
10722 
10723   PetscFunctionBegin;
10724   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10725   PetscCallMPI(MPI_Comm_size(comm, &size));
10726   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10727   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);
10728   *n    = 1;
10729   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10730   color = rank / k;
10731   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10732   PetscCall(PetscMalloc1(1, iss));
10733   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10734   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10735   PetscCallMPI(MPI_Comm_free(&subcomm));
10736   PetscFunctionReturn(0);
10737 }
10738 
10739 /*@
10740    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10741 
10742    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10743    If they are not the same, uses `MatMatMatMult()`.
10744 
10745    Once the coarse grid problem is constructed, correct for interpolation operators
10746    that are not of full rank, which can legitimately happen in the case of non-nested
10747    geometric multigrid.
10748 
10749    Input Parameters:
10750 +  restrct - restriction operator
10751 .  dA - fine grid matrix
10752 .  interpolate - interpolation operator
10753 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10754 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10755 
10756    Output Parameters:
10757 .  A - the Galerkin coarse matrix
10758 
10759    Options Database Key:
10760 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10761 
10762    Level: developer
10763 
10764 .seealso: `MatPtAP()`, `MatMatMatMult()`
10765 @*/
10766 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10767 {
10768   IS  zerorows;
10769   Vec diag;
10770 
10771   PetscFunctionBegin;
10772   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10773   /* Construct the coarse grid matrix */
10774   if (interpolate == restrct) {
10775     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10776   } else {
10777     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10778   }
10779 
10780   /* If the interpolation matrix is not of full rank, A will have zero rows.
10781      This can legitimately happen in the case of non-nested geometric multigrid.
10782      In that event, we set the rows of the matrix to the rows of the identity,
10783      ignoring the equations (as the RHS will also be zero). */
10784 
10785   PetscCall(MatFindZeroRows(*A, &zerorows));
10786 
10787   if (zerorows != NULL) { /* if there are any zero rows */
10788     PetscCall(MatCreateVecs(*A, &diag, NULL));
10789     PetscCall(MatGetDiagonal(*A, diag));
10790     PetscCall(VecISSet(diag, zerorows, 1.0));
10791     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10792     PetscCall(VecDestroy(&diag));
10793     PetscCall(ISDestroy(&zerorows));
10794   }
10795   PetscFunctionReturn(0);
10796 }
10797 
10798 /*@C
10799     MatSetOperation - Allows user to set a matrix operation for any matrix type
10800 
10801    Logically Collective on mat
10802 
10803     Input Parameters:
10804 +   mat - the matrix
10805 .   op - the name of the operation
10806 -   f - the function that provides the operation
10807 
10808    Level: developer
10809 
10810     Usage:
10811 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10812 $      PetscCall(MatCreateXXX(comm,...&A);
10813 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10814 
10815     Notes:
10816     See the file include/petscmat.h for a complete list of matrix
10817     operations, which all have the form MATOP_<OPERATION>, where
10818     <OPERATION> is the name (in all capital letters) of the
10819     user interface routine (e.g., MatMult() -> MATOP_MULT).
10820 
10821     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10822     sequence as the usual matrix interface routines, since they
10823     are intended to be accessed via the usual matrix interface
10824     routines, e.g.,
10825 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10826 
10827     In particular each function MUST return an error code of 0 on success and
10828     nonzero on failure.
10829 
10830     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10831 
10832 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10833 @*/
10834 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10835 {
10836   PetscFunctionBegin;
10837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10838   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10839   (((void (**)(void))mat->ops)[op]) = f;
10840   PetscFunctionReturn(0);
10841 }
10842 
10843 /*@C
10844     MatGetOperation - Gets a matrix operation for any matrix type.
10845 
10846     Not Collective
10847 
10848     Input Parameters:
10849 +   mat - the matrix
10850 -   op - the name of the operation
10851 
10852     Output Parameter:
10853 .   f - the function that provides the operation
10854 
10855     Level: developer
10856 
10857     Usage:
10858 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10859 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10860 
10861     Notes:
10862     See the file include/petscmat.h for a complete list of matrix
10863     operations, which all have the form MATOP_<OPERATION>, where
10864     <OPERATION> is the name (in all capital letters) of the
10865     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10866 
10867     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10868 
10869 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10870 @*/
10871 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10872 {
10873   PetscFunctionBegin;
10874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10875   *f = (((void (**)(void))mat->ops)[op]);
10876   PetscFunctionReturn(0);
10877 }
10878 
10879 /*@
10880     MatHasOperation - Determines whether the given matrix supports the particular operation.
10881 
10882    Not Collective
10883 
10884    Input Parameters:
10885 +  mat - the matrix
10886 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10887 
10888    Output Parameter:
10889 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10890 
10891    Level: advanced
10892 
10893    Note:
10894    See the file include/petscmat.h for a complete list of matrix
10895    operations, which all have the form MATOP_<OPERATION>, where
10896    <OPERATION> is the name (in all capital letters) of the
10897    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10898 
10899 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10900 @*/
10901 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10902 {
10903   PetscFunctionBegin;
10904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10905   PetscValidBoolPointer(has, 3);
10906   if (mat->ops->hasoperation) {
10907     PetscUseTypeMethod(mat, hasoperation, op, has);
10908   } else {
10909     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10910     else {
10911       *has = PETSC_FALSE;
10912       if (op == MATOP_CREATE_SUBMATRIX) {
10913         PetscMPIInt size;
10914 
10915         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10916         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10917       }
10918     }
10919   }
10920   PetscFunctionReturn(0);
10921 }
10922 
10923 /*@
10924     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10925 
10926    Collective on mat
10927 
10928    Input Parameters:
10929 .  mat - the matrix
10930 
10931    Output Parameter:
10932 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10933 
10934    Level: beginner
10935 
10936 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10937 @*/
10938 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10939 {
10940   PetscFunctionBegin;
10941   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10942   PetscValidType(mat, 1);
10943   PetscValidBoolPointer(cong, 2);
10944   if (!mat->rmap || !mat->cmap) {
10945     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10946     PetscFunctionReturn(0);
10947   }
10948   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10949     PetscCall(PetscLayoutSetUp(mat->rmap));
10950     PetscCall(PetscLayoutSetUp(mat->cmap));
10951     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10952     if (*cong) mat->congruentlayouts = 1;
10953     else mat->congruentlayouts = 0;
10954   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10955   PetscFunctionReturn(0);
10956 }
10957 
10958 PetscErrorCode MatSetInf(Mat A)
10959 {
10960   PetscFunctionBegin;
10961   PetscUseTypeMethod(A, setinf);
10962   PetscFunctionReturn(0);
10963 }
10964 
10965 /*C
10966    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
10967 
10968    Collective on mat
10969 
10970    Input Parameters:
10971 +  A - the matrix
10972 -  sym - `PETSC_TRUE` indicates that the graph will be symmetrized
10973 .  scale - `PETSC_TRUE` indicates that the graph will be scaled with the diagonal
10974 
10975    Output Parameter:
10976 .  graph - the resulting graph
10977 
10978    Level: advanced
10979 
10980 .seealso: `MatCreate()`, `MatFilter()`
10981 */
10982 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph)
10983 {
10984   PetscFunctionBegin;
10985   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
10986   PetscValidType(A, 1);
10987   PetscValidPointer(graph, 3);
10988   PetscUseTypeMethod(A, creategraph, sym, scale, graph);
10989   PetscFunctionReturn(0);
10990 }
10991 
10992 /*C
10993    MatFilter - filters a matrices values with an absolut value equal to or below a give threshold
10994 
10995    Collective on mat
10996 
10997    Input Parameter:
10998 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10999 
11000    Input/Output Parameter:
11001 .  A - the `Mat` to filter in place
11002 
11003    Level: developer
11004 
11005    Note:
11006    This is called before graph coarsers are called in `PCGAMG`
11007 
11008 .seealso: `MatCreate()`, `MatCreateGraph()`
11009 */
11010 PETSC_EXTERN PetscErrorCode MatFilter(Mat G, PetscReal value, Mat *F)
11011 {
11012   PetscFunctionBegin;
11013   PetscValidHeaderSpecific(G, MAT_CLASSID, 1);
11014   PetscValidType(G, 1);
11015   PetscValidPointer(F, 3);
11016   if (value >= 0.0) PetscCall((G->ops->filter)(G, value, F));
11017   PetscFunctionReturn(0);
11018 }
11019