xref: /petsc/src/mat/interface/matrix.c (revision 35cb6cd333087cc89d8d5031932d4f38af02614d)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36 PetscLogEvent MAT_GetMultiProcBlock;
37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
52                   for sparse matrices that already have locations it fills the locations with random numbers
53 
54    Logically Collective
55 
56    Input Parameters:
57 +  x  - the matrix
58 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
59           it will create one internally.
60 
61    Output Parameter:
62 .  x  - the matrix
63 
64    Example of Usage:
65 .vb
66      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
67      MatSetRandom(x,rctx);
68      PetscRandomDestroy(rctx);
69 .ve
70 
71    Level: intermediate
72 
73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
74 @*/
75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
76 {
77   PetscRandom randObj = NULL;
78 
79   PetscFunctionBegin;
80   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
81   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
82   PetscValidType(x, 1);
83   MatCheckPreallocated(x, 1);
84 
85   if (!rctx) {
86     MPI_Comm comm;
87     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
88     PetscCall(PetscRandomCreate(comm, &randObj));
89     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
90     PetscCall(PetscRandomSetFromOptions(randObj));
91     rctx = randObj;
92   }
93   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
94   PetscUseTypeMethod(x, setrandom, rctx);
95   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
96 
97   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
98   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
99   PetscCall(PetscRandomDestroy(&randObj));
100   PetscFunctionReturn(0);
101 }
102 
103 /*@
104    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
105 
106    Logically Collective
107 
108    Input Parameter:
109 .  mat - the factored matrix
110 
111    Output Parameters:
112 +  pivot - the pivot value computed
113 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
114          the share the matrix
115 
116    Level: advanced
117 
118    Notes:
119     This routine does not work for factorizations done with external packages.
120 
121     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
122 
123     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
124 
125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
126           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
127 @*/
128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
129 {
130   PetscFunctionBegin;
131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
132   PetscValidRealPointer(pivot, 2);
133   PetscValidIntPointer(row, 3);
134   *pivot = mat->factorerror_zeropivot_value;
135   *row   = mat->factorerror_zeropivot_row;
136   PetscFunctionReturn(0);
137 }
138 
139 /*@
140    MatFactorGetError - gets the error code from a factorization
141 
142    Logically Collective
143 
144    Input Parameters:
145 .  mat - the factored matrix
146 
147    Output Parameter:
148 .  err  - the error code
149 
150    Level: advanced
151 
152    Note:
153     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
154 
155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
156           `MatFactorError`
157 @*/
158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
159 {
160   PetscFunctionBegin;
161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
162   PetscValidPointer(err, 2);
163   *err = mat->factorerrortype;
164   PetscFunctionReturn(0);
165 }
166 
167 /*@
168    MatFactorClearError - clears the error code in a factorization
169 
170    Logically Collective
171 
172    Input Parameter:
173 .  mat - the factored matrix
174 
175    Level: developer
176 
177    Note:
178     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
179 
180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
181           `MatGetErrorCode()`, `MatFactorError`
182 @*/
183 PetscErrorCode MatFactorClearError(Mat mat)
184 {
185   PetscFunctionBegin;
186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
187   mat->factorerrortype             = MAT_FACTOR_NOERROR;
188   mat->factorerror_zeropivot_value = 0.0;
189   mat->factorerror_zeropivot_row   = 0;
190   PetscFunctionReturn(0);
191 }
192 
193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
194 {
195   Vec                r, l;
196   const PetscScalar *al;
197   PetscInt           i, nz, gnz, N, n;
198 
199   PetscFunctionBegin;
200   PetscCall(MatCreateVecs(mat, &r, &l));
201   if (!cols) { /* nonzero rows */
202     PetscCall(MatGetSize(mat, &N, NULL));
203     PetscCall(MatGetLocalSize(mat, &n, NULL));
204     PetscCall(VecSet(l, 0.0));
205     PetscCall(VecSetRandom(r, NULL));
206     PetscCall(MatMult(mat, r, l));
207     PetscCall(VecGetArrayRead(l, &al));
208   } else { /* nonzero columns */
209     PetscCall(MatGetSize(mat, NULL, &N));
210     PetscCall(MatGetLocalSize(mat, NULL, &n));
211     PetscCall(VecSet(r, 0.0));
212     PetscCall(VecSetRandom(l, NULL));
213     PetscCall(MatMultTranspose(mat, l, r));
214     PetscCall(VecGetArrayRead(r, &al));
215   }
216   if (tol <= 0.0) {
217     for (i = 0, nz = 0; i < n; i++)
218       if (al[i] != 0.0) nz++;
219   } else {
220     for (i = 0, nz = 0; i < n; i++)
221       if (PetscAbsScalar(al[i]) > tol) nz++;
222   }
223   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
224   if (gnz != N) {
225     PetscInt *nzr;
226     PetscCall(PetscMalloc1(nz, &nzr));
227     if (nz) {
228       if (tol < 0) {
229         for (i = 0, nz = 0; i < n; i++)
230           if (al[i] != 0.0) nzr[nz++] = i;
231       } else {
232         for (i = 0, nz = 0; i < n; i++)
233           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
234       }
235     }
236     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
237   } else *nonzero = NULL;
238   if (!cols) { /* nonzero rows */
239     PetscCall(VecRestoreArrayRead(l, &al));
240   } else {
241     PetscCall(VecRestoreArrayRead(r, &al));
242   }
243   PetscCall(VecDestroy(&l));
244   PetscCall(VecDestroy(&r));
245   PetscFunctionReturn(0);
246 }
247 
248 /*@
249       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
250 
251   Input Parameter:
252 .    A  - the matrix
253 
254   Output Parameter:
255 .    keptrows - the rows that are not completely zero
256 
257   Note:
258     keptrows is set to NULL if all rows are nonzero.
259 
260   Level: intermediate
261 
262 .seealso: `Mat`, `MatFindZeroRows()`
263  @*/
264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
265 {
266   PetscFunctionBegin;
267   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
268   PetscValidType(mat, 1);
269   PetscValidPointer(keptrows, 2);
270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
271   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
272   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
273   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
274   PetscFunctionReturn(0);
275 }
276 
277 /*@
278       MatFindZeroRows - Locate all rows that are completely zero in the matrix
279 
280   Input Parameter:
281 .    A  - the matrix
282 
283   Output Parameter:
284 .    zerorows - the rows that are completely zero
285 
286   Note:
287     zerorows is set to NULL if no rows are zero.
288 
289   Level: intermediate
290 
291 .seealso: `Mat`, `MatFindNonzeroRows()`
292  @*/
293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
294 {
295   IS       keptrows;
296   PetscInt m, n;
297 
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
300   PetscValidType(mat, 1);
301   PetscValidPointer(zerorows, 2);
302   PetscCall(MatFindNonzeroRows(mat, &keptrows));
303   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
304      In keeping with this convention, we set zerorows to NULL if there are no zero
305      rows. */
306   if (keptrows == NULL) {
307     *zerorows = NULL;
308   } else {
309     PetscCall(MatGetOwnershipRange(mat, &m, &n));
310     PetscCall(ISComplement(keptrows, m, n, zerorows));
311     PetscCall(ISDestroy(&keptrows));
312   }
313   PetscFunctionReturn(0);
314 }
315 
316 /*@
317    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
318 
319    Not Collective
320 
321    Input Parameters:
322 .   A - the matrix
323 
324    Output Parameters:
325 .   a - the diagonal part (which is a SEQUENTIAL matrix)
326 
327    Notes:
328    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
329 
330    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
331 
332    Level: advanced
333 
334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
335 @*/
336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
337 {
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
340   PetscValidType(A, 1);
341   PetscValidPointer(a, 2);
342   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
343   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
344   else {
345     PetscMPIInt size;
346 
347     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
348     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
349     *a = A;
350   }
351   PetscFunctionReturn(0);
352 }
353 
354 /*@
355    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
356 
357    Collective
358 
359    Input Parameters:
360 .  mat - the matrix
361 
362    Output Parameter:
363 .   trace - the sum of the diagonal entries
364 
365    Level: advanced
366 
367 .seealso: `Mat`
368 @*/
369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
370 {
371   Vec diag;
372 
373   PetscFunctionBegin;
374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
375   PetscValidScalarPointer(trace, 2);
376   PetscCall(MatCreateVecs(mat, &diag, NULL));
377   PetscCall(MatGetDiagonal(mat, diag));
378   PetscCall(VecSum(diag, trace));
379   PetscCall(VecDestroy(&diag));
380   PetscFunctionReturn(0);
381 }
382 
383 /*@
384    MatRealPart - Zeros out the imaginary part of the matrix
385 
386    Logically Collective
387 
388    Input Parameters:
389 .  mat - the matrix
390 
391    Level: advanced
392 
393 .seealso: `MatImaginaryPart()`
394 @*/
395 PetscErrorCode MatRealPart(Mat mat)
396 {
397   PetscFunctionBegin;
398   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
399   PetscValidType(mat, 1);
400   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
401   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
402   MatCheckPreallocated(mat, 1);
403   PetscUseTypeMethod(mat, realpart);
404   PetscFunctionReturn(0);
405 }
406 
407 /*@C
408    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
409 
410    Collective
411 
412    Input Parameter:
413 .  mat - the matrix
414 
415    Output Parameters:
416 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
417 -   ghosts - the global indices of the ghost points
418 
419    Note:
420     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
421 
422    Level: advanced
423 
424 .seealso: `Mat`, `VecCreateGhost()`
425 @*/
426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
427 {
428   PetscFunctionBegin;
429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
430   PetscValidType(mat, 1);
431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
433   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
434   else {
435     if (nghosts) *nghosts = 0;
436     if (ghosts) *ghosts = NULL;
437   }
438   PetscFunctionReturn(0);
439 }
440 
441 /*@
442    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
443 
444    Logically Collective
445 
446    Input Parameters:
447 .  mat - the matrix
448 
449    Level: advanced
450 
451 .seealso: `MatRealPart()`
452 @*/
453 PetscErrorCode MatImaginaryPart(Mat mat)
454 {
455   PetscFunctionBegin;
456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
457   PetscValidType(mat, 1);
458   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
459   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
460   MatCheckPreallocated(mat, 1);
461   PetscUseTypeMethod(mat, imaginarypart);
462   PetscFunctionReturn(0);
463 }
464 
465 /*@
466    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
467 
468    Not Collective
469 
470    Input Parameter:
471 .  mat - the matrix
472 
473    Output Parameters:
474 +  missing - is any diagonal missing
475 -  dd - first diagonal entry that is missing (optional) on this process
476 
477    Level: advanced
478 
479 .seealso: `Mat`
480 @*/
481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
482 {
483   PetscFunctionBegin;
484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
485   PetscValidType(mat, 1);
486   PetscValidBoolPointer(missing, 2);
487   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
488   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
489   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
490   PetscFunctionReturn(0);
491 }
492 
493 /*@C
494    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
495    for each row that you get to ensure that your application does
496    not bleed memory.
497 
498    Not Collective
499 
500    Input Parameters:
501 +  mat - the matrix
502 -  row - the row to get
503 
504    Output Parameters:
505 +  ncols -  if not NULL, the number of nonzeros in the row
506 .  cols - if not NULL, the column numbers
507 -  vals - if not NULL, the values
508 
509    Notes:
510    This routine is provided for people who need to have direct access
511    to the structure of a matrix.  We hope that we provide enough
512    high-level matrix routines that few users will need it.
513 
514    `MatGetRow()` always returns 0-based column indices, regardless of
515    whether the internal representation is 0-based (default) or 1-based.
516 
517    For better efficiency, set cols and/or vals to NULL if you do
518    not wish to extract these quantities.
519 
520    The user can only examine the values extracted with `MatGetRow()`;
521    the values cannot be altered.  To change the matrix entries, one
522    must use `MatSetValues()`.
523 
524    You can only have one call to `MatGetRow()` outstanding for a particular
525    matrix at a time, per processor. `MatGetRow()` can only obtain rows
526    associated with the given processor, it cannot get rows from the
527    other processors; for that we suggest using `MatCreateSubMatrices()`, then
528    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
529    is in the global number of rows.
530 
531    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
532 
533    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
534 
535    Fortran Note:
536    The calling sequence from Fortran is
537 .vb
538    MatGetRow(matrix,row,ncols,cols,values,ierr)
539          Mat     matrix (input)
540          integer row    (input)
541          integer ncols  (output)
542          integer cols(maxcols) (output)
543          double precision (or double complex) values(maxcols) output
544 .ve
545    where maxcols >= maximum nonzeros in any row of the matrix.
546 
547    Caution:
548    Do not try to change the contents of the output arrays (cols and vals).
549    In some cases, this may corrupt the matrix.
550 
551    Level: advanced
552 
553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
554 @*/
555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
556 {
557   PetscInt incols;
558 
559   PetscFunctionBegin;
560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
561   PetscValidType(mat, 1);
562   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
563   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
564   MatCheckPreallocated(mat, 1);
565   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
566   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
567   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
568   if (ncols) *ncols = incols;
569   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
570   PetscFunctionReturn(0);
571 }
572 
573 /*@
574    MatConjugate - replaces the matrix values with their complex conjugates
575 
576    Logically Collective
577 
578    Input Parameters:
579 .  mat - the matrix
580 
581    Level: advanced
582 
583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
584 @*/
585 PetscErrorCode MatConjugate(Mat mat)
586 {
587   PetscFunctionBegin;
588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
590   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
591     PetscUseTypeMethod(mat, conjugate);
592     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
593   }
594   PetscFunctionReturn(0);
595 }
596 
597 /*@C
598    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
599 
600    Not Collective
601 
602    Input Parameters:
603 +  mat - the matrix
604 .  row - the row to get
605 .  ncols, cols - the number of nonzeros and their columns
606 -  vals - if nonzero the column values
607 
608    Notes:
609    This routine should be called after you have finished examining the entries.
610 
611    This routine zeros out ncols, cols, and vals. This is to prevent accidental
612    us of the array after it has been restored. If you pass NULL, it will
613    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
614 
615    Fortran Notes:
616    The calling sequence from Fortran is
617 .vb
618    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
619       Mat     matrix (input)
620       integer row    (input)
621       integer ncols  (output)
622       integer cols(maxcols) (output)
623       double precision (or double complex) values(maxcols) output
624 .ve
625    Where maxcols >= maximum nonzeros in any row of the matrix.
626 
627    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
628    before another call to `MatGetRow()` can be made.
629 
630    Level: advanced
631 
632 .seealso: `MatGetRow()`
633 @*/
634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
635 {
636   PetscFunctionBegin;
637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
638   if (ncols) PetscValidIntPointer(ncols, 3);
639   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
640   if (!mat->ops->restorerow) PetscFunctionReturn(0);
641   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
642   if (ncols) *ncols = 0;
643   if (cols) *cols = NULL;
644   if (vals) *vals = NULL;
645   PetscFunctionReturn(0);
646 }
647 
648 /*@
649    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
650    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
651 
652    Not Collective
653 
654    Input Parameters:
655 .  mat - the matrix
656 
657    Note:
658    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
659 
660    Level: advanced
661 
662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
663 @*/
664 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
665 {
666   PetscFunctionBegin;
667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
668   PetscValidType(mat, 1);
669   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
670   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
671   MatCheckPreallocated(mat, 1);
672   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
673   PetscUseTypeMethod(mat, getrowuppertriangular);
674   PetscFunctionReturn(0);
675 }
676 
677 /*@
678    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
679 
680    Not Collective
681 
682    Input Parameters:
683 .  mat - the matrix
684 
685    Note:
686    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
687 
688    Level: advanced
689 
690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
701   PetscUseTypeMethod(mat, restorerowuppertriangular);
702   PetscFunctionReturn(0);
703 }
704 
705 /*@C
706    MatSetOptionsPrefix - Sets the prefix used for searching for all
707    `Mat` options in the database.
708 
709    Logically Collective on A
710 
711    Input Parameters:
712 +  A - the matrix
713 -  prefix - the prefix to prepend to all option names
714 
715    Notes:
716    A hyphen (-) must NOT be given at the beginning of the prefix name.
717    The first character of all runtime options is AUTOMATICALLY the hyphen.
718 
719    This is NOT used for options for the factorization of the matrix. Normally the
720    prefix is automatically passed in from the PC calling the factorization. To set
721    it directly use  `MatSetOptionsPrefixFactor()`
722 
723    Level: advanced
724 
725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
726 @*/
727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
728 {
729   PetscFunctionBegin;
730   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
731   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
732   PetscFunctionReturn(0);
733 }
734 
735 /*@C
736    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
737    for matrices created with `MatGetFactor()`
738 
739    Logically Collective on A
740 
741    Input Parameters:
742 +  A - the matrix
743 -  prefix - the prefix to prepend to all option names for the factored matrix
744 
745    Notes:
746    A hyphen (-) must NOT be given at the beginning of the prefix name.
747    The first character of all runtime options is AUTOMATICALLY the hyphen.
748 
749    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
750    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
751 
752    Level: developer
753 
754 .seealso:   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
755 @*/
756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
757 {
758   PetscFunctionBegin;
759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
760   if (prefix) {
761     PetscValidCharPointer(prefix, 2);
762     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
763     if (prefix != A->factorprefix) {
764       PetscCall(PetscFree(A->factorprefix));
765       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
766     }
767   } else PetscCall(PetscFree(A->factorprefix));
768   PetscFunctionReturn(0);
769 }
770 
771 /*@C
772    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
773    for matrices created with `MatGetFactor()`
774 
775    Logically Collective on A
776 
777    Input Parameters:
778 +  A - the matrix
779 -  prefix - the prefix to prepend to all option names for the factored matrix
780 
781    Notes:
782    A hyphen (-) must NOT be given at the beginning of the prefix name.
783    The first character of all runtime options is AUTOMATICALLY the hyphen.
784 
785    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
786    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
787 
788    Level: developer
789 
790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
791           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
792           `MatSetOptionsPrefix()`
793 @*/
794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
795 {
796   char  *buf = A->factorprefix;
797   size_t len1, len2;
798 
799   PetscFunctionBegin;
800   PetscValidHeader(A, 1);
801   if (!prefix) PetscFunctionReturn(0);
802   if (!buf) {
803     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
804     PetscFunctionReturn(0);
805   }
806   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
807 
808   PetscCall(PetscStrlen(prefix, &len1));
809   PetscCall(PetscStrlen(buf, &len2));
810   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
811   PetscCall(PetscStrcpy(A->factorprefix, buf));
812   PetscCall(PetscStrcat(A->factorprefix, prefix));
813   PetscCall(PetscFree(buf));
814   PetscFunctionReturn(0);
815 }
816 
817 /*@C
818    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
819    matrix options in the database.
820 
821    Logically Collective on A
822 
823    Input Parameters:
824 +  A - the matrix
825 -  prefix - the prefix to prepend to all option names
826 
827    Note:
828    A hyphen (-) must NOT be given at the beginning of the prefix name.
829    The first character of all runtime options is AUTOMATICALLY the hyphen.
830 
831    Level: advanced
832 
833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
834 @*/
835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
836 {
837   PetscFunctionBegin;
838   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
839   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
840   PetscFunctionReturn(0);
841 }
842 
843 /*@C
844    MatGetOptionsPrefix - Gets the prefix used for searching for all
845    matrix options in the database.
846 
847    Not Collective
848 
849    Input Parameter:
850 .  A - the matrix
851 
852    Output Parameter:
853 .  prefix - pointer to the prefix string used
854 
855    Level: advanced
856 
857    Fortran Note:
858     On the fortran side, the user should pass in a string 'prefix' of
859    sufficient length to hold the prefix.
860 
861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
862 @*/
863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
864 {
865   PetscFunctionBegin;
866   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
867   PetscValidPointer(prefix, 2);
868   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
869   PetscFunctionReturn(0);
870 }
871 
872 /*@
873    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
874 
875    Collective on A
876 
877    Input Parameters:
878 .  A - the matrix
879 
880    Notes:
881    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
882 
883    Users can reset the preallocation to access the original memory.
884 
885    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
886 
887    Level: beginner
888 
889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
890 @*/
891 PetscErrorCode MatResetPreallocation(Mat A)
892 {
893   PetscFunctionBegin;
894   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
895   PetscValidType(A, 1);
896   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
897   PetscFunctionReturn(0);
898 }
899 
900 /*@
901    MatSetUp - Sets up the internal matrix data structures for later use.
902 
903    Collective on A
904 
905    Input Parameters:
906 .  A - the matrix
907 
908    Notes:
909    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
910 
911    If a suitable preallocation routine is used, this function does not need to be called.
912 
913    See the Performance chapter of the PETSc users manual for how to preallocate matrices
914 
915    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
916 
917    Level: intermediate
918 
919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
920 @*/
921 PetscErrorCode MatSetUp(Mat A)
922 {
923   PetscFunctionBegin;
924   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
925   if (!((PetscObject)A)->type_name) {
926     PetscMPIInt size;
927 
928     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
929     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
930   }
931   if (!A->preallocated && A->ops->setup) {
932     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
933     PetscUseTypeMethod(A, setup);
934   }
935   PetscCall(PetscLayoutSetUp(A->rmap));
936   PetscCall(PetscLayoutSetUp(A->cmap));
937   A->preallocated = PETSC_TRUE;
938   PetscFunctionReturn(0);
939 }
940 
941 #if defined(PETSC_HAVE_SAWS)
942   #include <petscviewersaws.h>
943 #endif
944 
945 /*@C
946    MatViewFromOptions - View properties of the matrix from the options database
947 
948    Collective on A
949 
950    Input Parameters:
951 +  A - the matrix
952 .  obj - optional additional object that provides the options prefix to use
953 -  name - command line option
954 
955   Options Database Key:
956 .  -mat_view [viewertype]:... - the viewer and its options
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970    Level: intermediate
971 
972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
973 @*/
974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
975 {
976   PetscFunctionBegin;
977   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
978   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
979   PetscFunctionReturn(0);
980 }
981 
982 /*@C
983    MatView - display information about a matrix in a variety ways
984 
985    Collective
986 
987    Input Parameters:
988 +  mat - the matrix
989 -  viewer - visualization context
990 
991   Notes:
992   The available visualization contexts include
993 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
994 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
995 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
996 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
997 
998    The user can open alternative visualization contexts with
999 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1000 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1001          specified file; corresponding input uses MatLoad()
1002 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1003          an X window display
1004 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1005          Currently only the sequential dense and AIJ
1006          matrix types support the Socket viewer.
1007 
1008    The user can call `PetscViewerPushFormat()` to specify the output
1009    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1010    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1011 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1012 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1013 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1014 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1015          format common among all matrix types
1016 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1017          format (which is in many cases the same as the default)
1018 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1019          size and structure (not the matrix entries)
1020 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1021          the matrix structure
1022 
1023    Options Database Keys:
1024 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1025 .  -mat_view ::ascii_info_detail - Prints more detailed info
1026 .  -mat_view - Prints matrix in ASCII format
1027 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1028 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1029 .  -display <name> - Sets display name (default is host)
1030 .  -draw_pause <sec> - Sets number of seconds to pause after display
1031 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1032 .  -viewer_socket_machine <machine> -
1033 .  -viewer_socket_port <port> -
1034 .  -mat_view binary - save matrix to file in binary format
1035 -  -viewer_binary_filename <name> -
1036 
1037    Level: beginner
1038 
1039    Notes:
1040     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1041     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1042 
1043     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1044 
1045     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1046       viewer is used.
1047 
1048       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1049       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1050 
1051       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1052       and then use the following mouse functions.
1053 .vb
1054   left mouse: zoom in
1055   middle mouse: zoom out
1056   right mouse: continue with the simulation
1057 .ve
1058 
1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1060           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1061 @*/
1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1063 {
1064   PetscInt          rows, cols, rbs, cbs;
1065   PetscBool         isascii, isstring, issaws;
1066   PetscViewerFormat format;
1067   PetscMPIInt       size;
1068 
1069   PetscFunctionBegin;
1070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1071   PetscValidType(mat, 1);
1072   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1073   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1074   PetscCheckSameComm(mat, 1, viewer, 2);
1075 
1076   PetscCall(PetscViewerGetFormat(viewer, &format));
1077   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1078   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1079 
1080   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1081   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1082   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1083   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1084 
1085   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1086   if (isascii) {
1087     if (!mat->preallocated) {
1088       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1089       PetscFunctionReturn(0);
1090     }
1091     if (!mat->assembled) {
1092       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1093       PetscFunctionReturn(0);
1094     }
1095     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1096     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1097       MatNullSpace nullsp, transnullsp;
1098 
1099       PetscCall(PetscViewerASCIIPushTab(viewer));
1100       PetscCall(MatGetSize(mat, &rows, &cols));
1101       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1102       if (rbs != 1 || cbs != 1) {
1103         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1104         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1105       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1106       if (mat->factortype) {
1107         MatSolverType solver;
1108         PetscCall(MatFactorGetSolverType(mat, &solver));
1109         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1110       }
1111       if (mat->ops->getinfo) {
1112         MatInfo info;
1113         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1114         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1115         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1116       }
1117       PetscCall(MatGetNullSpace(mat, &nullsp));
1118       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1120       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1121       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1122       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1123       PetscCall(PetscViewerASCIIPushTab(viewer));
1124       PetscCall(MatProductView(mat, viewer));
1125       PetscCall(PetscViewerASCIIPopTab(viewer));
1126     }
1127   } else if (issaws) {
1128 #if defined(PETSC_HAVE_SAWS)
1129     PetscMPIInt rank;
1130 
1131     PetscCall(PetscObjectName((PetscObject)mat));
1132     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1133     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1134 #endif
1135   } else if (isstring) {
1136     const char *type;
1137     PetscCall(MatGetType(mat, &type));
1138     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1139     PetscTryTypeMethod(mat, view, viewer);
1140   }
1141   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1142     PetscCall(PetscViewerASCIIPushTab(viewer));
1143     PetscUseTypeMethod(mat, viewnative, viewer);
1144     PetscCall(PetscViewerASCIIPopTab(viewer));
1145   } else if (mat->ops->view) {
1146     PetscCall(PetscViewerASCIIPushTab(viewer));
1147     PetscUseTypeMethod(mat, view, viewer);
1148     PetscCall(PetscViewerASCIIPopTab(viewer));
1149   }
1150   if (isascii) {
1151     PetscCall(PetscViewerGetFormat(viewer, &format));
1152     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1153   }
1154   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1155   PetscFunctionReturn(0);
1156 }
1157 
1158 #if defined(PETSC_USE_DEBUG)
1159   #include <../src/sys/totalview/tv_data_display.h>
1160 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1161 {
1162   TV_add_row("Local rows", "int", &mat->rmap->n);
1163   TV_add_row("Local columns", "int", &mat->cmap->n);
1164   TV_add_row("Global rows", "int", &mat->rmap->N);
1165   TV_add_row("Global columns", "int", &mat->cmap->N);
1166   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1167   return TV_format_OK;
1168 }
1169 #endif
1170 
1171 /*@C
1172    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1173    with `MatView()`.  The matrix format is determined from the options database.
1174    Generates a parallel MPI matrix if the communicator has more than one
1175    processor.  The default matrix type is `MATAIJ`.
1176 
1177    Collective
1178 
1179    Input Parameters:
1180 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1181             or some related function before a call to `MatLoad()`
1182 -  viewer - binary/HDF5 file viewer
1183 
1184    Options Database Keys:
1185    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1186    block size
1187 .    -matload_block_size <bs> - set block size
1188 
1189    Level: beginner
1190 
1191    Notes:
1192    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1193    `Mat` before calling this routine if you wish to set it from the options database.
1194 
1195    `MatLoad()` automatically loads into the options database any options
1196    given in the file filename.info where filename is the name of the file
1197    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1198    file will be ignored if you use the -viewer_binary_skip_info option.
1199 
1200    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1201    sets the default matrix type AIJ and sets the local and global sizes.
1202    If type and/or size is already set, then the same are used.
1203 
1204    In parallel, each processor can load a subset of rows (or the
1205    entire matrix).  This routine is especially useful when a large
1206    matrix is stored on disk and only part of it is desired on each
1207    processor.  For example, a parallel solver may access only some of
1208    the rows from each processor.  The algorithm used here reads
1209    relatively small blocks of data rather than reading the entire
1210    matrix and then subsetting it.
1211 
1212    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1213    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1214    or the sequence like
1215 .vb
1216     `PetscViewer` v;
1217     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1218     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1219     `PetscViewerSetFromOptions`(v);
1220     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1221     `PetscViewerFileSetName`(v,"datafile");
1222 .ve
1223    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1224 $ -viewer_type {binary,hdf5}
1225 
1226    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1227    and src/mat/tutorials/ex10.c with the second approach.
1228 
1229    Notes about the PETSc binary format:
1230    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1231    is read onto rank 0 and then shipped to its destination rank, one after another.
1232    Multiple objects, both matrices and vectors, can be stored within the same file.
1233    Their PetscObject name is ignored; they are loaded in the order of their storage.
1234 
1235    Most users should not need to know the details of the binary storage
1236    format, since `MatLoad()` and `MatView()` completely hide these details.
1237    But for anyone who's interested, the standard binary matrix storage
1238    format is
1239 
1240 $    PetscInt    MAT_FILE_CLASSID
1241 $    PetscInt    number of rows
1242 $    PetscInt    number of columns
1243 $    PetscInt    total number of nonzeros
1244 $    PetscInt    *number nonzeros in each row
1245 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1246 $    PetscScalar *values of all nonzeros
1247 
1248    PETSc automatically does the byte swapping for
1249 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1250 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1251 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1252 and `PetscBinaryWrite()` to see how this may be done.
1253 
1254    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1255    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1256    Each processor's chunk is loaded independently by its owning rank.
1257    Multiple objects, both matrices and vectors, can be stored within the same file.
1258    They are looked up by their PetscObject name.
1259 
1260    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1261    by default the same structure and naming of the AIJ arrays and column count
1262    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1263 $    save example.mat A b -v7.3
1264    can be directly read by this routine (see Reference 1 for details).
1265    Note that depending on your MATLAB version, this format might be a default,
1266    otherwise you can set it as default in Preferences.
1267 
1268    Unless -nocompression flag is used to save the file in MATLAB,
1269    PETSc must be configured with ZLIB package.
1270 
1271    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1272 
1273    Current HDF5 (MAT-File) limitations:
1274    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1275 
1276    Corresponding `MatView()` is not yet implemented.
1277 
1278    The loaded matrix is actually a transpose of the original one in MATLAB,
1279    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1280    With this format, matrix is automatically transposed by PETSc,
1281    unless the matrix is marked as SPD or symmetric
1282    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1283 
1284    References:
1285 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1286 
1287 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1288  @*/
1289 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1290 {
1291   PetscBool flg;
1292 
1293   PetscFunctionBegin;
1294   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1295   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1296 
1297   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1298 
1299   flg = PETSC_FALSE;
1300   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1301   if (flg) {
1302     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1303     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1304   }
1305   flg = PETSC_FALSE;
1306   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1307   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1308 
1309   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1310   PetscUseTypeMethod(mat, load, viewer);
1311   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1312   PetscFunctionReturn(0);
1313 }
1314 
1315 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1316 {
1317   Mat_Redundant *redund = *redundant;
1318 
1319   PetscFunctionBegin;
1320   if (redund) {
1321     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1322       PetscCall(ISDestroy(&redund->isrow));
1323       PetscCall(ISDestroy(&redund->iscol));
1324       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1325     } else {
1326       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1327       PetscCall(PetscFree(redund->sbuf_j));
1328       PetscCall(PetscFree(redund->sbuf_a));
1329       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1330         PetscCall(PetscFree(redund->rbuf_j[i]));
1331         PetscCall(PetscFree(redund->rbuf_a[i]));
1332       }
1333       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1334     }
1335 
1336     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1337     PetscCall(PetscFree(redund));
1338   }
1339   PetscFunctionReturn(0);
1340 }
1341 
1342 /*@C
1343    MatDestroy - Frees space taken by a matrix.
1344 
1345    Collective on A
1346 
1347    Input Parameter:
1348 .  A - the matrix
1349 
1350    Level: beginner
1351 
1352    Developer Note:
1353    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1354    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1355    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1356    if changes are needed here.
1357 
1358 .seealso: `Mat`, `MatCreate()`
1359 @*/
1360 PetscErrorCode MatDestroy(Mat *A)
1361 {
1362   PetscFunctionBegin;
1363   if (!*A) PetscFunctionReturn(0);
1364   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1365   if (--((PetscObject)(*A))->refct > 0) {
1366     *A = NULL;
1367     PetscFunctionReturn(0);
1368   }
1369 
1370   /* if memory was published with SAWs then destroy it */
1371   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1372   PetscTryTypeMethod((*A), destroy);
1373 
1374   PetscCall(PetscFree((*A)->factorprefix));
1375   PetscCall(PetscFree((*A)->defaultvectype));
1376   PetscCall(PetscFree((*A)->defaultrandtype));
1377   PetscCall(PetscFree((*A)->bsizes));
1378   PetscCall(PetscFree((*A)->solvertype));
1379   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1380   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1381   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1382   PetscCall(MatProductClear(*A));
1383   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1384   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1385   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1386   PetscCall(MatDestroy(&(*A)->schur));
1387   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1388   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1389   PetscCall(PetscHeaderDestroy(A));
1390   PetscFunctionReturn(0);
1391 }
1392 
1393 /*@C
1394    MatSetValues - Inserts or adds a block of values into a matrix.
1395    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1396    MUST be called after all calls to `MatSetValues()` have been completed.
1397 
1398    Not Collective
1399 
1400    Input Parameters:
1401 +  mat - the matrix
1402 .  v - a logically two-dimensional array of values
1403 .  m, idxm - the number of rows and their global indices
1404 .  n, idxn - the number of columns and their global indices
1405 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1406 
1407    Notes:
1408    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1409       `MatSetUp()` before using this routine
1410 
1411    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1412 
1413    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1414    options cannot be mixed without intervening calls to the assembly
1415    routines.
1416 
1417    `MatSetValues()` uses 0-based row and column numbers in Fortran
1418    as well as in C.
1419 
1420    Negative indices may be passed in idxm and idxn, these rows and columns are
1421    simply ignored. This allows easily inserting element stiffness matrices
1422    with homogeneous Dirchlet boundary conditions that you don't want represented
1423    in the matrix.
1424 
1425    Efficiency Alert:
1426    The routine `MatSetValuesBlocked()` may offer much better efficiency
1427    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1428 
1429    Level: beginner
1430 
1431    Developer Note:
1432    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1433    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1434 
1435 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1436           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1437 @*/
1438 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1439 {
1440   PetscFunctionBeginHot;
1441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1442   PetscValidType(mat, 1);
1443   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1444   PetscValidIntPointer(idxm, 3);
1445   PetscValidIntPointer(idxn, 5);
1446   MatCheckPreallocated(mat, 1);
1447 
1448   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1449   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1450 
1451   if (PetscDefined(USE_DEBUG)) {
1452     PetscInt i, j;
1453 
1454     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1455     for (i = 0; i < m; i++) {
1456       for (j = 0; j < n; j++) {
1457         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1458 #if defined(PETSC_USE_COMPLEX)
1459           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1460 #else
1461           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1462 #endif
1463       }
1464     }
1465     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1466     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1467   }
1468 
1469   if (mat->assembled) {
1470     mat->was_assembled = PETSC_TRUE;
1471     mat->assembled     = PETSC_FALSE;
1472   }
1473   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1474   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1475   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1476   PetscFunctionReturn(0);
1477 }
1478 
1479 /*@C
1480    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1481    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1482    MUST be called after all calls to `MatSetValues()` have been completed.
1483 
1484    Not Collective
1485 
1486    Input Parameters:
1487 +  mat - the matrix
1488 .  v - a logically two-dimensional array of values
1489 .  ism - the rows to provide
1490 .  isn - the columns to provide
1491 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1492 
1493    Level: beginner
1494 
1495    Notes:
1496    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1497       `MatSetUp()` before using this routine
1498 
1499    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1500 
1501    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1502    options cannot be mixed without intervening calls to the assembly
1503    routines.
1504 
1505    `MatSetValues()` uses 0-based row and column numbers in Fortran
1506    as well as in C.
1507 
1508    Negative indices may be passed in ism and isn, these rows and columns are
1509    simply ignored. This allows easily inserting element stiffness matrices
1510    with homogeneous Dirchlet boundary conditions that you don't want represented
1511    in the matrix.
1512 
1513    Efficiency Alert:
1514    The routine `MatSetValuesBlocked()` may offer much better efficiency
1515    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1516 
1517     This is currently not optimized for any particular `ISType`
1518 
1519    Developer Notes:
1520     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1521                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1522 
1523 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1524           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1525 @*/
1526 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1527 {
1528   PetscInt        m, n;
1529   const PetscInt *rows, *cols;
1530 
1531   PetscFunctionBeginHot;
1532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1533   PetscCall(ISGetIndices(ism, &rows));
1534   PetscCall(ISGetIndices(isn, &cols));
1535   PetscCall(ISGetLocalSize(ism, &m));
1536   PetscCall(ISGetLocalSize(isn, &n));
1537   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1538   PetscCall(ISRestoreIndices(ism, &rows));
1539   PetscCall(ISRestoreIndices(isn, &cols));
1540   PetscFunctionReturn(0);
1541 }
1542 
1543 /*@
1544    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1545         values into a matrix
1546 
1547    Not Collective
1548 
1549    Input Parameters:
1550 +  mat - the matrix
1551 .  row - the (block) row to set
1552 -  v - a logically two-dimensional array of values
1553 
1554    Notes:
1555    By the values, v, are column-oriented (for the block version) and sorted
1556 
1557    All the nonzeros in the row must be provided
1558 
1559    The matrix must have previously had its column indices set
1560 
1561    The row must belong to this process
1562 
1563    Level: intermediate
1564 
1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1566           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1567 @*/
1568 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1569 {
1570   PetscInt globalrow;
1571 
1572   PetscFunctionBegin;
1573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1574   PetscValidType(mat, 1);
1575   PetscValidScalarPointer(v, 3);
1576   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1577   PetscCall(MatSetValuesRow(mat, globalrow, v));
1578   PetscFunctionReturn(0);
1579 }
1580 
1581 /*@
1582    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1583         values into a matrix
1584 
1585    Not Collective
1586 
1587    Input Parameters:
1588 +  mat - the matrix
1589 .  row - the (block) row to set
1590 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1591 
1592    Notes:
1593    The values, v, are column-oriented for the block version.
1594 
1595    All the nonzeros in the row must be provided
1596 
1597    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1598 
1599    The row must belong to this process
1600 
1601    Level: advanced
1602 
1603 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1604           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1605 @*/
1606 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1607 {
1608   PetscFunctionBeginHot;
1609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1610   PetscValidType(mat, 1);
1611   MatCheckPreallocated(mat, 1);
1612   PetscValidScalarPointer(v, 3);
1613   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1614   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1615   mat->insertmode = INSERT_VALUES;
1616 
1617   if (mat->assembled) {
1618     mat->was_assembled = PETSC_TRUE;
1619     mat->assembled     = PETSC_FALSE;
1620   }
1621   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1622   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1623   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1624   PetscFunctionReturn(0);
1625 }
1626 
1627 /*@
1628    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1629      Using structured grid indexing
1630 
1631    Not Collective
1632 
1633    Input Parameters:
1634 +  mat - the matrix
1635 .  m - number of rows being entered
1636 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1637 .  n - number of columns being entered
1638 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1639 .  v - a logically two-dimensional array of values
1640 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1641 
1642    Level: beginner
1643 
1644    Notes:
1645    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1646 
1647    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1648    options cannot be mixed without intervening calls to the assembly
1649    routines.
1650 
1651    The grid coordinates are across the entire grid, not just the local portion
1652 
1653    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1654    as well as in C.
1655 
1656    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1657 
1658    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1659    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1660 
1661    The columns and rows in the stencil passed in MUST be contained within the
1662    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1663    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1664    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1665    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1666 
1667    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1668    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1669    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1670    `DM_BOUNDARY_PERIODIC` boundary type.
1671 
1672    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1673    a single value per point) you can skip filling those indices.
1674 
1675    Inspired by the structured grid interface to the HYPRE package
1676    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1677 
1678    Efficiency Alert:
1679    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1680    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1681 
1682    Fortran Note:
1683    In Fortran idxm and idxn should be declared as
1684 $     MatStencil idxm(4,m),idxn(4,n)
1685    and the values inserted using
1686 .vb
1687     idxm(MatStencil_i,1) = i
1688     idxm(MatStencil_j,1) = j
1689     idxm(MatStencil_k,1) = k
1690     idxm(MatStencil_c,1) = c
1691     etc
1692 .ve
1693 
1694 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1695           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1696 @*/
1697 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1698 {
1699   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1700   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1701   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1702 
1703   PetscFunctionBegin;
1704   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1705   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1706   PetscValidType(mat, 1);
1707   PetscValidPointer(idxm, 3);
1708   PetscValidPointer(idxn, 5);
1709 
1710   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1711     jdxm = buf;
1712     jdxn = buf + m;
1713   } else {
1714     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1715     jdxm = bufm;
1716     jdxn = bufn;
1717   }
1718   for (i = 0; i < m; i++) {
1719     for (j = 0; j < 3 - sdim; j++) dxm++;
1720     tmp = *dxm++ - starts[0];
1721     for (j = 0; j < dim - 1; j++) {
1722       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1723       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1724     }
1725     if (mat->stencil.noc) dxm++;
1726     jdxm[i] = tmp;
1727   }
1728   for (i = 0; i < n; i++) {
1729     for (j = 0; j < 3 - sdim; j++) dxn++;
1730     tmp = *dxn++ - starts[0];
1731     for (j = 0; j < dim - 1; j++) {
1732       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1733       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1734     }
1735     if (mat->stencil.noc) dxn++;
1736     jdxn[i] = tmp;
1737   }
1738   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1739   PetscCall(PetscFree2(bufm, bufn));
1740   PetscFunctionReturn(0);
1741 }
1742 
1743 /*@
1744    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1745      Using structured grid indexing
1746 
1747    Not Collective
1748 
1749    Input Parameters:
1750 +  mat - the matrix
1751 .  m - number of rows being entered
1752 .  idxm - grid coordinates for matrix rows being entered
1753 .  n - number of columns being entered
1754 .  idxn - grid coordinates for matrix columns being entered
1755 .  v - a logically two-dimensional array of values
1756 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1757 
1758    Level: beginner
1759 
1760    Notes:
1761    By default the values, v, are row-oriented and unsorted.
1762    See `MatSetOption()` for other options.
1763 
1764    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1765    options cannot be mixed without intervening calls to the assembly
1766    routines.
1767 
1768    The grid coordinates are across the entire grid, not just the local portion
1769 
1770    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1771    as well as in C.
1772 
1773    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1774 
1775    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1776    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1777 
1778    The columns and rows in the stencil passed in MUST be contained within the
1779    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1780    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1781    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1782    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1783 
1784    Negative indices may be passed in idxm and idxn, these rows and columns are
1785    simply ignored. This allows easily inserting element stiffness matrices
1786    with homogeneous Dirchlet boundary conditions that you don't want represented
1787    in the matrix.
1788 
1789    Inspired by the structured grid interface to the HYPRE package
1790    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1791 
1792    Fortran Note:
1793    In Fortran idxm and idxn should be declared as
1794 $     MatStencil idxm(4,m),idxn(4,n)
1795    and the values inserted using
1796 .vb
1797     idxm(MatStencil_i,1) = i
1798     idxm(MatStencil_j,1) = j
1799     idxm(MatStencil_k,1) = k
1800    etc
1801 .ve
1802 
1803 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1804           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1805           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1806 @*/
1807 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1808 {
1809   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1810   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1811   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1812 
1813   PetscFunctionBegin;
1814   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1816   PetscValidType(mat, 1);
1817   PetscValidPointer(idxm, 3);
1818   PetscValidPointer(idxn, 5);
1819   PetscValidScalarPointer(v, 6);
1820 
1821   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1822     jdxm = buf;
1823     jdxn = buf + m;
1824   } else {
1825     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1826     jdxm = bufm;
1827     jdxn = bufn;
1828   }
1829   for (i = 0; i < m; i++) {
1830     for (j = 0; j < 3 - sdim; j++) dxm++;
1831     tmp = *dxm++ - starts[0];
1832     for (j = 0; j < sdim - 1; j++) {
1833       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1834       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1835     }
1836     dxm++;
1837     jdxm[i] = tmp;
1838   }
1839   for (i = 0; i < n; i++) {
1840     for (j = 0; j < 3 - sdim; j++) dxn++;
1841     tmp = *dxn++ - starts[0];
1842     for (j = 0; j < sdim - 1; j++) {
1843       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1844       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1845     }
1846     dxn++;
1847     jdxn[i] = tmp;
1848   }
1849   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1850   PetscCall(PetscFree2(bufm, bufn));
1851   PetscFunctionReturn(0);
1852 }
1853 
1854 /*@
1855    MatSetStencil - Sets the grid information for setting values into a matrix via
1856         `MatSetValuesStencil()`
1857 
1858    Not Collective
1859 
1860    Input Parameters:
1861 +  mat - the matrix
1862 .  dim - dimension of the grid 1, 2, or 3
1863 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1864 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1865 -  dof - number of degrees of freedom per node
1866 
1867    Notes:
1868    Inspired by the structured grid interface to the HYPRE package
1869    (www.llnl.gov/CASC/hyper)
1870 
1871    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1872    user.
1873 
1874    Level: beginner
1875 
1876 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1877           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1878 @*/
1879 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1880 {
1881   PetscFunctionBegin;
1882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1883   PetscValidIntPointer(dims, 3);
1884   PetscValidIntPointer(starts, 4);
1885 
1886   mat->stencil.dim = dim + (dof > 1);
1887   for (PetscInt i = 0; i < dim; i++) {
1888     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1889     mat->stencil.starts[i] = starts[dim - i - 1];
1890   }
1891   mat->stencil.dims[dim]   = dof;
1892   mat->stencil.starts[dim] = 0;
1893   mat->stencil.noc         = (PetscBool)(dof == 1);
1894   PetscFunctionReturn(0);
1895 }
1896 
1897 /*@C
1898    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1899 
1900    Not Collective
1901 
1902    Input Parameters:
1903 +  mat - the matrix
1904 .  v - a logically two-dimensional array of values
1905 .  m, idxm - the number of block rows and their global block indices
1906 .  n, idxn - the number of block columns and their global block indices
1907 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1908 
1909    Level: intermediate
1910 
1911    Notes:
1912    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1913    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1914 
1915    The m and n count the NUMBER of blocks in the row direction and column direction,
1916    NOT the total number of rows/columns; for example, if the block size is 2 and
1917    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1918    The values in idxm would be 1 2; that is the first index for each block divided by
1919    the block size.
1920 
1921    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1922    preallocating it).
1923 
1924    By default the values, v, are row-oriented, so the layout of
1925    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1926 
1927    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1928    options cannot be mixed without intervening calls to the assembly
1929    routines.
1930 
1931    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1932    as well as in C.
1933 
1934    Negative indices may be passed in idxm and idxn, these rows and columns are
1935    simply ignored. This allows easily inserting element stiffness matrices
1936    with homogeneous Dirchlet boundary conditions that you don't want represented
1937    in the matrix.
1938 
1939    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1940    internal searching must be done to determine where to place the
1941    data in the matrix storage space.  By instead inserting blocks of
1942    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1943    reduced.
1944 
1945    Example:
1946 .vb
1947    Suppose m=n=2 and block size(bs) = 2 The array is
1948 
1949    1  2  | 3  4
1950    5  6  | 7  8
1951    - - - | - - -
1952    9  10 | 11 12
1953    13 14 | 15 16
1954 
1955    v[] should be passed in like
1956    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1957 
1958   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1959    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1960 .ve
1961 
1962 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1963 @*/
1964 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1965 {
1966   PetscFunctionBeginHot;
1967   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1968   PetscValidType(mat, 1);
1969   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1970   PetscValidIntPointer(idxm, 3);
1971   PetscValidIntPointer(idxn, 5);
1972   MatCheckPreallocated(mat, 1);
1973   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1974   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1975   if (PetscDefined(USE_DEBUG)) {
1976     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1977     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1978   }
1979   if (PetscDefined(USE_DEBUG)) {
1980     PetscInt rbs, cbs, M, N, i;
1981     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1982     PetscCall(MatGetSize(mat, &M, &N));
1983     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1984     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1985   }
1986   if (mat->assembled) {
1987     mat->was_assembled = PETSC_TRUE;
1988     mat->assembled     = PETSC_FALSE;
1989   }
1990   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1991   if (mat->ops->setvaluesblocked) {
1992     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1993   } else {
1994     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1995     PetscInt i, j, bs, cbs;
1996 
1997     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1998     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1999       iidxm = buf;
2000       iidxn = buf + m * bs;
2001     } else {
2002       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2003       iidxm = bufr;
2004       iidxn = bufc;
2005     }
2006     for (i = 0; i < m; i++) {
2007       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2008     }
2009     if (m != n || bs != cbs || idxm != idxn) {
2010       for (i = 0; i < n; i++) {
2011         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2012       }
2013     } else iidxn = iidxm;
2014     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2015     PetscCall(PetscFree2(bufr, bufc));
2016   }
2017   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2018   PetscFunctionReturn(0);
2019 }
2020 
2021 /*@C
2022    MatGetValues - Gets a block of local values from a matrix.
2023 
2024    Not Collective; can only return values that are owned by the give process
2025 
2026    Input Parameters:
2027 +  mat - the matrix
2028 .  v - a logically two-dimensional array for storing the values
2029 .  m, idxm - the number of rows and their global indices
2030 -  n, idxn - the number of columns and their global indices
2031 
2032    Notes:
2033      The user must allocate space (m*n `PetscScalar`s) for the values, v.
2034      The values, v, are then returned in a row-oriented format,
2035      analogous to that used by default in `MatSetValues()`.
2036 
2037      `MatGetValues()` uses 0-based row and column numbers in
2038      Fortran as well as in C.
2039 
2040      `MatGetValues()` requires that the matrix has been assembled
2041      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2042      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2043      without intermediate matrix assembly.
2044 
2045      Negative row or column indices will be ignored and those locations in v[] will be
2046      left unchanged.
2047 
2048      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2049      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2050      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2051 
2052    Level: advanced
2053 
2054 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2055 @*/
2056 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2057 {
2058   PetscFunctionBegin;
2059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2060   PetscValidType(mat, 1);
2061   if (!m || !n) PetscFunctionReturn(0);
2062   PetscValidIntPointer(idxm, 3);
2063   PetscValidIntPointer(idxn, 5);
2064   PetscValidScalarPointer(v, 6);
2065   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2066   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2067   MatCheckPreallocated(mat, 1);
2068 
2069   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2070   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2071   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2072   PetscFunctionReturn(0);
2073 }
2074 
2075 /*@C
2076    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2077      defined previously by `MatSetLocalToGlobalMapping()`
2078 
2079    Not Collective
2080 
2081    Input Parameters:
2082 +  mat - the matrix
2083 .  nrow, irow - number of rows and their local indices
2084 -  ncol, icol - number of columns and their local indices
2085 
2086    Output Parameter:
2087 .  y -  a logically two-dimensional array of values
2088 
2089    Level: advanced
2090 
2091    Notes:
2092      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2093 
2094      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2095      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2096      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2097      with `MatSetLocalToGlobalMapping()`.
2098 
2099    Developer Note:
2100       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2101       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2102 
2103 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2104           `MatSetValuesLocal()`, `MatGetValues()`
2105 @*/
2106 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2107 {
2108   PetscFunctionBeginHot;
2109   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2110   PetscValidType(mat, 1);
2111   MatCheckPreallocated(mat, 1);
2112   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2113   PetscValidIntPointer(irow, 3);
2114   PetscValidIntPointer(icol, 5);
2115   if (PetscDefined(USE_DEBUG)) {
2116     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2117     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2118   }
2119   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2120   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2121   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2122   else {
2123     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2124     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2125       irowm = buf;
2126       icolm = buf + nrow;
2127     } else {
2128       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2129       irowm = bufr;
2130       icolm = bufc;
2131     }
2132     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2133     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2134     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2135     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2136     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2137     PetscCall(PetscFree2(bufr, bufc));
2138   }
2139   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2140   PetscFunctionReturn(0);
2141 }
2142 
2143 /*@
2144   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2145   the same size. Currently, this can only be called once and creates the given matrix.
2146 
2147   Not Collective
2148 
2149   Input Parameters:
2150 + mat - the matrix
2151 . nb - the number of blocks
2152 . bs - the number of rows (and columns) in each block
2153 . rows - a concatenation of the rows for each block
2154 - v - a concatenation of logically two-dimensional arrays of values
2155 
2156   Note:
2157   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2158 
2159   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2160 
2161   Level: advanced
2162 
2163 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2164           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2165 @*/
2166 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2167 {
2168   PetscFunctionBegin;
2169   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2170   PetscValidType(mat, 1);
2171   PetscValidIntPointer(rows, 4);
2172   PetscValidScalarPointer(v, 5);
2173   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2174 
2175   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2176   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2177   else {
2178     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2179   }
2180   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2181   PetscFunctionReturn(0);
2182 }
2183 
2184 /*@
2185    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2186    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2187    using a local (per-processor) numbering.
2188 
2189    Not Collective
2190 
2191    Input Parameters:
2192 +  x - the matrix
2193 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2194 -  cmapping - column mapping
2195 
2196    Level: intermediate
2197 
2198    Note:
2199    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2200 
2201 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2202 @*/
2203 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2204 {
2205   PetscFunctionBegin;
2206   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2207   PetscValidType(x, 1);
2208   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2209   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2210   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2211   else {
2212     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2213     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2214   }
2215   PetscFunctionReturn(0);
2216 }
2217 
2218 /*@
2219    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2220 
2221    Not Collective
2222 
2223    Input Parameter:
2224 .  A - the matrix
2225 
2226    Output Parameters:
2227 + rmapping - row mapping
2228 - cmapping - column mapping
2229 
2230    Level: advanced
2231 
2232 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2233 @*/
2234 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2235 {
2236   PetscFunctionBegin;
2237   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2238   PetscValidType(A, 1);
2239   if (rmapping) {
2240     PetscValidPointer(rmapping, 2);
2241     *rmapping = A->rmap->mapping;
2242   }
2243   if (cmapping) {
2244     PetscValidPointer(cmapping, 3);
2245     *cmapping = A->cmap->mapping;
2246   }
2247   PetscFunctionReturn(0);
2248 }
2249 
2250 /*@
2251    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2252 
2253    Logically Collective on A
2254 
2255    Input Parameters:
2256 +  A - the matrix
2257 . rmap - row layout
2258 - cmap - column layout
2259 
2260    Level: advanced
2261 
2262    Note:
2263    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2264 
2265 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2266 @*/
2267 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2268 {
2269   PetscFunctionBegin;
2270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2271   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2272   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2273   PetscFunctionReturn(0);
2274 }
2275 
2276 /*@
2277    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2278 
2279    Not Collective
2280 
2281    Input Parameter:
2282 .  A - the matrix
2283 
2284    Output Parameters:
2285 + rmap - row layout
2286 - cmap - column layout
2287 
2288    Level: advanced
2289 
2290 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2291 @*/
2292 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2293 {
2294   PetscFunctionBegin;
2295   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2296   PetscValidType(A, 1);
2297   if (rmap) {
2298     PetscValidPointer(rmap, 2);
2299     *rmap = A->rmap;
2300   }
2301   if (cmap) {
2302     PetscValidPointer(cmap, 3);
2303     *cmap = A->cmap;
2304   }
2305   PetscFunctionReturn(0);
2306 }
2307 
2308 /*@C
2309    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2310    using a local numbering of the nodes.
2311 
2312    Not Collective
2313 
2314    Input Parameters:
2315 +  mat - the matrix
2316 .  nrow, irow - number of rows and their local indices
2317 .  ncol, icol - number of columns and their local indices
2318 .  y -  a logically two-dimensional array of values
2319 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2320 
2321    Notes:
2322    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2323       `MatSetUp()` before using this routine
2324 
2325    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2326 
2327    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2328    options cannot be mixed without intervening calls to the assembly
2329    routines.
2330 
2331    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2332    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2333 
2334    Level: intermediate
2335 
2336    Developer Note:
2337     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2338                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2339 
2340 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2341           `MatGetValuesLocal()`
2342 @*/
2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2344 {
2345   PetscFunctionBeginHot;
2346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2347   PetscValidType(mat, 1);
2348   MatCheckPreallocated(mat, 1);
2349   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2350   PetscValidIntPointer(irow, 3);
2351   PetscValidIntPointer(icol, 5);
2352   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2353   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2354   if (PetscDefined(USE_DEBUG)) {
2355     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2356     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2357   }
2358 
2359   if (mat->assembled) {
2360     mat->was_assembled = PETSC_TRUE;
2361     mat->assembled     = PETSC_FALSE;
2362   }
2363   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2364   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2365   else {
2366     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2367     const PetscInt *irowm, *icolm;
2368 
2369     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2370       bufr  = buf;
2371       bufc  = buf + nrow;
2372       irowm = bufr;
2373       icolm = bufc;
2374     } else {
2375       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2376       irowm = bufr;
2377       icolm = bufc;
2378     }
2379     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2380     else irowm = irow;
2381     if (mat->cmap->mapping) {
2382       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2383         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2384       } else icolm = irowm;
2385     } else icolm = icol;
2386     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2387     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2388   }
2389   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2390   PetscFunctionReturn(0);
2391 }
2392 
2393 /*@C
2394    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2395    using a local ordering of the nodes a block at a time.
2396 
2397    Not Collective
2398 
2399    Input Parameters:
2400 +  x - the matrix
2401 .  nrow, irow - number of rows and their local indices
2402 .  ncol, icol - number of columns and their local indices
2403 .  y -  a logically two-dimensional array of values
2404 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2405 
2406    Notes:
2407    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2408       `MatSetUp()` before using this routine
2409 
2410    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2411       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2412 
2413    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2414    options cannot be mixed without intervening calls to the assembly
2415    routines.
2416 
2417    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2418    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2419 
2420    Level: intermediate
2421 
2422    Developer Note:
2423     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2424                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2425 
2426 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2427           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2428 @*/
2429 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2430 {
2431   PetscFunctionBeginHot;
2432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2433   PetscValidType(mat, 1);
2434   MatCheckPreallocated(mat, 1);
2435   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2436   PetscValidIntPointer(irow, 3);
2437   PetscValidIntPointer(icol, 5);
2438   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2439   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2440   if (PetscDefined(USE_DEBUG)) {
2441     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2442     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2443   }
2444 
2445   if (mat->assembled) {
2446     mat->was_assembled = PETSC_TRUE;
2447     mat->assembled     = PETSC_FALSE;
2448   }
2449   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2450     PetscInt irbs, rbs;
2451     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2452     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2453     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2454   }
2455   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2456     PetscInt icbs, cbs;
2457     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2458     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2459     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2460   }
2461   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2462   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2463   else {
2464     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2465     const PetscInt *irowm, *icolm;
2466 
2467     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2468       bufr  = buf;
2469       bufc  = buf + nrow;
2470       irowm = bufr;
2471       icolm = bufc;
2472     } else {
2473       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2474       irowm = bufr;
2475       icolm = bufc;
2476     }
2477     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2478     else irowm = irow;
2479     if (mat->cmap->mapping) {
2480       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2481         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2482       } else icolm = irowm;
2483     } else icolm = icol;
2484     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2485     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2486   }
2487   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2488   PetscFunctionReturn(0);
2489 }
2490 
2491 /*@
2492    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2493 
2494    Collective
2495 
2496    Input Parameters:
2497 +  mat - the matrix
2498 -  x   - the vector to be multiplied
2499 
2500    Output Parameters:
2501 .  y - the result
2502 
2503    Note:
2504    The vectors x and y cannot be the same.  I.e., one cannot
2505    call `MatMultDiagonalBlock`(A,y,y).
2506 
2507    Level: developer
2508 
2509 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2510 @*/
2511 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2512 {
2513   PetscFunctionBegin;
2514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2515   PetscValidType(mat, 1);
2516   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2517   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2518 
2519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2520   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2521   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2522   MatCheckPreallocated(mat, 1);
2523 
2524   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2525   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2526   PetscFunctionReturn(0);
2527 }
2528 
2529 /* --------------------------------------------------------*/
2530 /*@
2531    MatMult - Computes the matrix-vector product, y = Ax.
2532 
2533    Neighbor-wise Collective
2534 
2535    Input Parameters:
2536 +  mat - the matrix
2537 -  x   - the vector to be multiplied
2538 
2539    Output Parameters:
2540 .  y - the result
2541 
2542    Note:
2543    The vectors x and y cannot be the same.  I.e., one cannot
2544    call `MatMult`(A,y,y).
2545 
2546    Level: beginner
2547 
2548 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2549 @*/
2550 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2551 {
2552   PetscFunctionBegin;
2553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2554   PetscValidType(mat, 1);
2555   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2556   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2558   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2559   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2560   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2561   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2562   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2563   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2564   PetscCall(VecSetErrorIfLocked(y, 3));
2565   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2566   MatCheckPreallocated(mat, 1);
2567 
2568   PetscCall(VecLockReadPush(x));
2569   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2570   PetscUseTypeMethod(mat, mult, x, y);
2571   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2572   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2573   PetscCall(VecLockReadPop(x));
2574   PetscFunctionReturn(0);
2575 }
2576 
2577 /*@
2578    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2579 
2580    Neighbor-wise Collective
2581 
2582    Input Parameters:
2583 +  mat - the matrix
2584 -  x   - the vector to be multiplied
2585 
2586    Output Parameters:
2587 .  y - the result
2588 
2589    Notes:
2590    The vectors x and y cannot be the same.  I.e., one cannot
2591    call `MatMultTranspose`(A,y,y).
2592 
2593    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2594    use `MatMultHermitianTranspose()`
2595 
2596    Level: beginner
2597 
2598 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2599 @*/
2600 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2601 {
2602   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2603 
2604   PetscFunctionBegin;
2605   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2606   PetscValidType(mat, 1);
2607   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2608   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2609 
2610   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2611   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2612   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2613   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2614   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2615   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2616   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2617   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2618   MatCheckPreallocated(mat, 1);
2619 
2620   if (!mat->ops->multtranspose) {
2621     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2622     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2623   } else op = mat->ops->multtranspose;
2624   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2625   PetscCall(VecLockReadPush(x));
2626   PetscCall((*op)(mat, x, y));
2627   PetscCall(VecLockReadPop(x));
2628   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2629   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2630   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2631   PetscFunctionReturn(0);
2632 }
2633 
2634 /*@
2635    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2636 
2637    Neighbor-wise Collective
2638 
2639    Input Parameters:
2640 +  mat - the matrix
2641 -  x   - the vector to be multilplied
2642 
2643    Output Parameters:
2644 .  y - the result
2645 
2646    Notes:
2647    The vectors x and y cannot be the same.  I.e., one cannot
2648    call `MatMultHermitianTranspose`(A,y,y).
2649 
2650    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2651 
2652    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2653 
2654    Level: beginner
2655 
2656 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2657 @*/
2658 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2659 {
2660   PetscFunctionBegin;
2661   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2662   PetscValidType(mat, 1);
2663   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2664   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2665 
2666   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2667   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2668   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2669   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2670   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2671   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2672   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2673   MatCheckPreallocated(mat, 1);
2674 
2675   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2676 #if defined(PETSC_USE_COMPLEX)
2677   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2678     PetscCall(VecLockReadPush(x));
2679     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2680     else PetscUseTypeMethod(mat, mult, x, y);
2681     PetscCall(VecLockReadPop(x));
2682   } else {
2683     Vec w;
2684     PetscCall(VecDuplicate(x, &w));
2685     PetscCall(VecCopy(x, w));
2686     PetscCall(VecConjugate(w));
2687     PetscCall(MatMultTranspose(mat, w, y));
2688     PetscCall(VecDestroy(&w));
2689     PetscCall(VecConjugate(y));
2690   }
2691   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2692 #else
2693   PetscCall(MatMultTranspose(mat, x, y));
2694 #endif
2695   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2696   PetscFunctionReturn(0);
2697 }
2698 
2699 /*@
2700     MatMultAdd -  Computes v3 = v2 + A * v1.
2701 
2702     Neighbor-wise Collective
2703 
2704     Input Parameters:
2705 +   mat - the matrix
2706 -   v1, v2 - the vectors
2707 
2708     Output Parameters:
2709 .   v3 - the result
2710 
2711     Note:
2712     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2713     call `MatMultAdd`(A,v1,v2,v1).
2714 
2715     Level: beginner
2716 
2717 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2718 @*/
2719 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2720 {
2721   PetscFunctionBegin;
2722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2723   PetscValidType(mat, 1);
2724   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2725   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2726   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2727 
2728   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2729   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2730   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2731   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2732      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2733   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2734   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2735   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2736   MatCheckPreallocated(mat, 1);
2737 
2738   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2739   PetscCall(VecLockReadPush(v1));
2740   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2741   PetscCall(VecLockReadPop(v1));
2742   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2743   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2744   PetscFunctionReturn(0);
2745 }
2746 
2747 /*@
2748    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2749 
2750    Neighbor-wise Collective
2751 
2752    Input Parameters:
2753 +  mat - the matrix
2754 -  v1, v2 - the vectors
2755 
2756    Output Parameters:
2757 .  v3 - the result
2758 
2759    Note:
2760    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2761    call `MatMultTransposeAdd`(A,v1,v2,v1).
2762 
2763    Level: beginner
2764 
2765 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2766 @*/
2767 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2768 {
2769   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2770 
2771   PetscFunctionBegin;
2772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2773   PetscValidType(mat, 1);
2774   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2775   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2776   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2777 
2778   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2779   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2780   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2781   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2782   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2783   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2784   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2785   MatCheckPreallocated(mat, 1);
2786 
2787   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2788   PetscCall(VecLockReadPush(v1));
2789   PetscCall((*op)(mat, v1, v2, v3));
2790   PetscCall(VecLockReadPop(v1));
2791   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2792   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2793   PetscFunctionReturn(0);
2794 }
2795 
2796 /*@
2797    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2798 
2799    Neighbor-wise Collective
2800 
2801    Input Parameters:
2802 +  mat - the matrix
2803 -  v1, v2 - the vectors
2804 
2805    Output Parameters:
2806 .  v3 - the result
2807 
2808    Note:
2809    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2810    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2811 
2812    Level: beginner
2813 
2814 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2815 @*/
2816 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2817 {
2818   PetscFunctionBegin;
2819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2820   PetscValidType(mat, 1);
2821   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2822   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2823   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2824 
2825   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2826   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2827   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2828   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2829   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2830   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2831   MatCheckPreallocated(mat, 1);
2832 
2833   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2834   PetscCall(VecLockReadPush(v1));
2835   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2836   else {
2837     Vec w, z;
2838     PetscCall(VecDuplicate(v1, &w));
2839     PetscCall(VecCopy(v1, w));
2840     PetscCall(VecConjugate(w));
2841     PetscCall(VecDuplicate(v3, &z));
2842     PetscCall(MatMultTranspose(mat, w, z));
2843     PetscCall(VecDestroy(&w));
2844     PetscCall(VecConjugate(z));
2845     if (v2 != v3) {
2846       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2847     } else {
2848       PetscCall(VecAXPY(v3, 1.0, z));
2849     }
2850     PetscCall(VecDestroy(&z));
2851   }
2852   PetscCall(VecLockReadPop(v1));
2853   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2854   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2855   PetscFunctionReturn(0);
2856 }
2857 
2858 /*@C
2859    MatGetFactorType - gets the type of factorization it is
2860 
2861    Not Collective
2862 
2863    Input Parameters:
2864 .  mat - the matrix
2865 
2866    Output Parameters:
2867 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2868 
2869    Level: intermediate
2870 
2871 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2872           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2873 @*/
2874 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2875 {
2876   PetscFunctionBegin;
2877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2878   PetscValidType(mat, 1);
2879   PetscValidPointer(t, 2);
2880   *t = mat->factortype;
2881   PetscFunctionReturn(0);
2882 }
2883 
2884 /*@C
2885    MatSetFactorType - sets the type of factorization it is
2886 
2887    Logically Collective
2888 
2889    Input Parameters:
2890 +  mat - the matrix
2891 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2892 
2893    Level: intermediate
2894 
2895 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2896           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2897 @*/
2898 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2899 {
2900   PetscFunctionBegin;
2901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2902   PetscValidType(mat, 1);
2903   mat->factortype = t;
2904   PetscFunctionReturn(0);
2905 }
2906 
2907 /* ------------------------------------------------------------*/
2908 /*@C
2909    MatGetInfo - Returns information about matrix storage (number of
2910    nonzeros, memory, etc.).
2911 
2912    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2913 
2914    Input Parameter:
2915 .  mat - the matrix
2916 
2917    Output Parameters:
2918 +  flag - flag indicating the type of parameters to be returned
2919    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2920    MAT_GLOBAL_SUM - sum over all processors)
2921 -  info - matrix information context
2922 
2923    Notes:
2924    The `MatInfo` context contains a variety of matrix data, including
2925    number of nonzeros allocated and used, number of mallocs during
2926    matrix assembly, etc.  Additional information for factored matrices
2927    is provided (such as the fill ratio, number of mallocs during
2928    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2929    when using the runtime options
2930 $       -info -mat_view ::ascii_info
2931 
2932    Example for C/C++ Users:
2933    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2934    data within the MatInfo context.  For example,
2935 .vb
2936       MatInfo info;
2937       Mat     A;
2938       double  mal, nz_a, nz_u;
2939 
2940       MatGetInfo(A,MAT_LOCAL,&info);
2941       mal  = info.mallocs;
2942       nz_a = info.nz_allocated;
2943 .ve
2944 
2945    Example for Fortran Users:
2946    Fortran users should declare info as a double precision
2947    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2948    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2949    a complete list of parameter names.
2950 .vb
2951       double  precision info(MAT_INFO_SIZE)
2952       double  precision mal, nz_a
2953       Mat     A
2954       integer ierr
2955 
2956       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2957       mal = info(MAT_INFO_MALLOCS)
2958       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2959 .ve
2960 
2961     Level: intermediate
2962 
2963     Developer Note:
2964     Fortran interface is not autogenerated as the
2965     interface definition cannot be generated correctly [due to MatInfo]
2966 
2967 .seealso: `MatInfo`, `MatStashGetInfo()`
2968 @*/
2969 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2970 {
2971   PetscFunctionBegin;
2972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2973   PetscValidType(mat, 1);
2974   PetscValidPointer(info, 3);
2975   MatCheckPreallocated(mat, 1);
2976   PetscUseTypeMethod(mat, getinfo, flag, info);
2977   PetscFunctionReturn(0);
2978 }
2979 
2980 /*
2981    This is used by external packages where it is not easy to get the info from the actual
2982    matrix factorization.
2983 */
2984 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2985 {
2986   PetscFunctionBegin;
2987   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2988   PetscFunctionReturn(0);
2989 }
2990 
2991 /* ----------------------------------------------------------*/
2992 
2993 /*@C
2994    MatLUFactor - Performs in-place LU factorization of matrix.
2995 
2996    Collective
2997 
2998    Input Parameters:
2999 +  mat - the matrix
3000 .  row - row permutation
3001 .  col - column permutation
3002 -  info - options for factorization, includes
3003 $          fill - expected fill as ratio of original fill.
3004 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3005 $                   Run with the option -info to determine an optimal value to use
3006 
3007    Notes:
3008    Most users should employ the `KSP` interface for linear solvers
3009    instead of working directly with matrix algebra routines such as this.
3010    See, e.g., `KSPCreate()`.
3011 
3012    This changes the state of the matrix to a factored matrix; it cannot be used
3013    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3014 
3015    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3016    when not using `KSP`.
3017 
3018    Level: developer
3019 
3020    Developer Note:
3021    The Fortran interface is not autogenerated as the
3022    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3023 
3024 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3025           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3026 @*/
3027 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3028 {
3029   MatFactorInfo tinfo;
3030 
3031   PetscFunctionBegin;
3032   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3033   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3034   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3035   if (info) PetscValidPointer(info, 4);
3036   PetscValidType(mat, 1);
3037   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3038   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3039   MatCheckPreallocated(mat, 1);
3040   if (!info) {
3041     PetscCall(MatFactorInfoInitialize(&tinfo));
3042     info = &tinfo;
3043   }
3044 
3045   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3046   PetscUseTypeMethod(mat, lufactor, row, col, info);
3047   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3048   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3049   PetscFunctionReturn(0);
3050 }
3051 
3052 /*@C
3053    MatILUFactor - Performs in-place ILU factorization of matrix.
3054 
3055    Collective
3056 
3057    Input Parameters:
3058 +  mat - the matrix
3059 .  row - row permutation
3060 .  col - column permutation
3061 -  info - structure containing
3062 $      levels - number of levels of fill.
3063 $      expected fill - as ratio of original fill.
3064 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3065                 missing diagonal entries)
3066 
3067    Level: developer
3068 
3069    Notes:
3070    Most users should employ the `KSP` interface for linear solvers
3071    instead of working directly with matrix algebra routines such as this.
3072    See, e.g., `KSPCreate()`.
3073 
3074    Probably really in-place only when level of fill is zero, otherwise allocates
3075    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3076    when not using `KSP`.
3077 
3078    Developer Note:
3079    The Fortran interface is not autogenerated as the
3080    interface definition cannot be generated correctly [due to MatFactorInfo]
3081 
3082 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3083 @*/
3084 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3085 {
3086   PetscFunctionBegin;
3087   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3088   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3089   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3090   PetscValidPointer(info, 4);
3091   PetscValidType(mat, 1);
3092   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3093   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3094   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3095   MatCheckPreallocated(mat, 1);
3096 
3097   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3098   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3099   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3100   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3101   PetscFunctionReturn(0);
3102 }
3103 
3104 /*@C
3105    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3106    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3107 
3108    Collective on fact
3109 
3110    Input Parameters:
3111 +  fact - the factor matrix obtained with `MatGetFactor()`
3112 .  mat - the matrix
3113 .  row, col - row and column permutations
3114 -  info - options for factorization, includes
3115 .vb
3116           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3117           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3118 .ve
3119 
3120    Level: developer
3121 
3122    Notes:
3123     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3124 
3125    Most users should employ the simplified `KSP` interface for linear solvers
3126    instead of working directly with matrix algebra routines such as this.
3127    See, e.g., `KSPCreate()`.
3128 
3129    Developer Note:
3130    The Fortran interface is not autogenerated as the
3131    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3132 
3133 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3134 @*/
3135 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3136 {
3137   MatFactorInfo tinfo;
3138 
3139   PetscFunctionBegin;
3140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3141   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3142   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3143   if (info) PetscValidPointer(info, 5);
3144   PetscValidType(mat, 2);
3145   PetscValidPointer(fact, 1);
3146   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3147   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3148   if (!(fact)->ops->lufactorsymbolic) {
3149     MatSolverType stype;
3150     PetscCall(MatFactorGetSolverType(fact, &stype));
3151     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3152   }
3153   MatCheckPreallocated(mat, 2);
3154   if (!info) {
3155     PetscCall(MatFactorInfoInitialize(&tinfo));
3156     info = &tinfo;
3157   }
3158 
3159   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3160   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3161   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3162   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3163   PetscFunctionReturn(0);
3164 }
3165 
3166 /*@C
3167    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3168    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3169 
3170    Collective on fact
3171 
3172    Input Parameters:
3173 +  fact - the factor matrix obtained with `MatGetFactor()`
3174 .  mat - the matrix
3175 -  info - options for factorization
3176 
3177    Level: developer
3178 
3179    Notes:
3180    See `MatLUFactor()` for in-place factorization.  See
3181    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3182 
3183    Most users should employ the `KSP` interface for linear solvers
3184    instead of working directly with matrix algebra routines such as this.
3185    See, e.g., `KSPCreate()`.
3186 
3187     Developer Note:
3188     The Fortran interface is not autogenerated as the
3189     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3190 
3191 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3192 @*/
3193 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3194 {
3195   MatFactorInfo tinfo;
3196 
3197   PetscFunctionBegin;
3198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3199   PetscValidType(mat, 2);
3200   PetscValidPointer(fact, 1);
3201   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3202   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3203   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3204              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3205 
3206   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3207   MatCheckPreallocated(mat, 2);
3208   if (!info) {
3209     PetscCall(MatFactorInfoInitialize(&tinfo));
3210     info = &tinfo;
3211   }
3212 
3213   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3214   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3215   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3216   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3217   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3218   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3219   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3220   PetscFunctionReturn(0);
3221 }
3222 
3223 /*@C
3224    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3225    symmetric matrix.
3226 
3227    Collective
3228 
3229    Input Parameters:
3230 +  mat - the matrix
3231 .  perm - row and column permutations
3232 -  f - expected fill as ratio of original fill
3233 
3234    Level: developer
3235 
3236    Notes:
3237    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3238    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3239 
3240    Most users should employ the `KSP` interface for linear solvers
3241    instead of working directly with matrix algebra routines such as this.
3242    See, e.g., `KSPCreate()`.
3243 
3244    Developer Note:
3245    The Fortran interface is not autogenerated as the
3246    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3247 
3248 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3249           `MatGetOrdering()`
3250 @*/
3251 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3252 {
3253   MatFactorInfo tinfo;
3254 
3255   PetscFunctionBegin;
3256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3257   PetscValidType(mat, 1);
3258   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3259   if (info) PetscValidPointer(info, 3);
3260   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3263   MatCheckPreallocated(mat, 1);
3264   if (!info) {
3265     PetscCall(MatFactorInfoInitialize(&tinfo));
3266     info = &tinfo;
3267   }
3268 
3269   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3270   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3271   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3272   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3273   PetscFunctionReturn(0);
3274 }
3275 
3276 /*@C
3277    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3278    of a symmetric matrix.
3279 
3280    Collective on fact
3281 
3282    Input Parameters:
3283 +  fact - the factor matrix obtained with `MatGetFactor()`
3284 .  mat - the matrix
3285 .  perm - row and column permutations
3286 -  info - options for factorization, includes
3287 .vb
3288           fill - expected fill as ratio of original fill.
3289           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3290                    Run with the option -info to determine an optimal value to use
3291 .ve
3292 
3293    Level: developer
3294 
3295    Notes:
3296    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3297    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3298 
3299    Most users should employ the `KSP` interface for linear solvers
3300    instead of working directly with matrix algebra routines such as this.
3301    See, e.g., `KSPCreate()`.
3302 
3303    Developer Note:
3304    The Fortran interface is not autogenerated as the
3305    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3306 
3307 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3308           `MatGetOrdering()`
3309 @*/
3310 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3311 {
3312   MatFactorInfo tinfo;
3313 
3314   PetscFunctionBegin;
3315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3316   PetscValidType(mat, 2);
3317   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3318   if (info) PetscValidPointer(info, 4);
3319   PetscValidPointer(fact, 1);
3320   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3321   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3322   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3323   if (!(fact)->ops->choleskyfactorsymbolic) {
3324     MatSolverType stype;
3325     PetscCall(MatFactorGetSolverType(fact, &stype));
3326     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3327   }
3328   MatCheckPreallocated(mat, 2);
3329   if (!info) {
3330     PetscCall(MatFactorInfoInitialize(&tinfo));
3331     info = &tinfo;
3332   }
3333 
3334   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3335   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3336   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3337   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3338   PetscFunctionReturn(0);
3339 }
3340 
3341 /*@C
3342    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3343    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3344    `MatCholeskyFactorSymbolic()`.
3345 
3346    Collective on fact
3347 
3348    Input Parameters:
3349 +  fact - the factor matrix obtained with `MatGetFactor()`
3350 .  mat - the initial matrix
3351 .  info - options for factorization
3352 -  fact - the symbolic factor of mat
3353 
3354    Level: developer
3355 
3356    Note:
3357    Most users should employ the `KSP` interface for linear solvers
3358    instead of working directly with matrix algebra routines such as this.
3359    See, e.g., `KSPCreate()`.
3360 
3361    Developer Note:
3362    The Fortran interface is not autogenerated as the
3363    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3364 
3365 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3366 @*/
3367 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3368 {
3369   MatFactorInfo tinfo;
3370 
3371   PetscFunctionBegin;
3372   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3373   PetscValidType(mat, 2);
3374   PetscValidPointer(fact, 1);
3375   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3376   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3377   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3378   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3379              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3380   MatCheckPreallocated(mat, 2);
3381   if (!info) {
3382     PetscCall(MatFactorInfoInitialize(&tinfo));
3383     info = &tinfo;
3384   }
3385 
3386   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3387   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3388   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3389   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3390   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3391   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3392   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3393   PetscFunctionReturn(0);
3394 }
3395 
3396 /*@
3397    MatQRFactor - Performs in-place QR factorization of matrix.
3398 
3399    Collective
3400 
3401    Input Parameters:
3402 +  mat - the matrix
3403 .  col - column permutation
3404 -  info - options for factorization, includes
3405 .vb
3406           fill - expected fill as ratio of original fill.
3407           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3408                    Run with the option -info to determine an optimal value to use
3409 .ve
3410 
3411    Level: developer
3412 
3413    Notes:
3414    Most users should employ the `KSP` interface for linear solvers
3415    instead of working directly with matrix algebra routines such as this.
3416    See, e.g., `KSPCreate()`.
3417 
3418    This changes the state of the matrix to a factored matrix; it cannot be used
3419    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3420 
3421    Developer Note:
3422    The Fortran interface is not autogenerated as the
3423    interface definition cannot be generated correctly [due to MatFactorInfo]
3424 
3425 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3426           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3427 @*/
3428 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3429 {
3430   PetscFunctionBegin;
3431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3432   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3433   if (info) PetscValidPointer(info, 3);
3434   PetscValidType(mat, 1);
3435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3437   MatCheckPreallocated(mat, 1);
3438   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3439   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3440   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3441   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3442   PetscFunctionReturn(0);
3443 }
3444 
3445 /*@
3446    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3447    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3448 
3449    Collective on fact
3450 
3451    Input Parameters:
3452 +  fact - the factor matrix obtained with `MatGetFactor()`
3453 .  mat - the matrix
3454 .  col - column permutation
3455 -  info - options for factorization, includes
3456 .vb
3457           fill - expected fill as ratio of original fill.
3458           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3459                    Run with the option -info to determine an optimal value to use
3460 .ve
3461 
3462    Level: developer
3463 
3464    Note:
3465    Most users should employ the `KSP` interface for linear solvers
3466    instead of working directly with matrix algebra routines such as this.
3467    See, e.g., `KSPCreate()`.
3468 
3469    Developer Note:
3470    The Fortran interface is not autogenerated as the
3471    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3472 
3473 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3474 @*/
3475 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3476 {
3477   MatFactorInfo tinfo;
3478 
3479   PetscFunctionBegin;
3480   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3481   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3482   if (info) PetscValidPointer(info, 4);
3483   PetscValidType(mat, 2);
3484   PetscValidPointer(fact, 1);
3485   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3486   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3487   MatCheckPreallocated(mat, 2);
3488   if (!info) {
3489     PetscCall(MatFactorInfoInitialize(&tinfo));
3490     info = &tinfo;
3491   }
3492 
3493   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3494   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3495   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3496   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3497   PetscFunctionReturn(0);
3498 }
3499 
3500 /*@
3501    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3502    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3503 
3504    Collective on fact
3505 
3506    Input Parameters:
3507 +  fact - the factor matrix obtained with `MatGetFactor()`
3508 .  mat - the matrix
3509 -  info - options for factorization
3510 
3511    Level: developer
3512 
3513    Notes:
3514    See `MatQRFactor()` for in-place factorization.
3515 
3516    Most users should employ the `KSP` interface for linear solvers
3517    instead of working directly with matrix algebra routines such as this.
3518    See, e.g., `KSPCreate()`.
3519 
3520    Developer Note:
3521    The Fortran interface is not autogenerated as the
3522    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3523 
3524 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3525 @*/
3526 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3527 {
3528   MatFactorInfo tinfo;
3529 
3530   PetscFunctionBegin;
3531   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3532   PetscValidType(mat, 2);
3533   PetscValidPointer(fact, 1);
3534   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3535   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3536   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3537              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3538 
3539   MatCheckPreallocated(mat, 2);
3540   if (!info) {
3541     PetscCall(MatFactorInfoInitialize(&tinfo));
3542     info = &tinfo;
3543   }
3544 
3545   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3546   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3547   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3548   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3549   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3550   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3551   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3552   PetscFunctionReturn(0);
3553 }
3554 
3555 /* ----------------------------------------------------------------*/
3556 /*@
3557    MatSolve - Solves A x = b, given a factored matrix.
3558 
3559    Neighbor-wise Collective
3560 
3561    Input Parameters:
3562 +  mat - the factored matrix
3563 -  b - the right-hand-side vector
3564 
3565    Output Parameter:
3566 .  x - the result vector
3567 
3568    Notes:
3569    The vectors b and x cannot be the same.  I.e., one cannot
3570    call `MatSolve`(A,x,x).
3571 
3572    Most users should employ the `KSP` interface for linear solvers
3573    instead of working directly with matrix algebra routines such as this.
3574    See, e.g., `KSPCreate()`.
3575 
3576    Level: developer
3577 
3578 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3579 @*/
3580 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3581 {
3582   PetscFunctionBegin;
3583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3584   PetscValidType(mat, 1);
3585   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3586   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3587   PetscCheckSameComm(mat, 1, b, 2);
3588   PetscCheckSameComm(mat, 1, x, 3);
3589   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3590   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3591   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3592   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3593   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3594   MatCheckPreallocated(mat, 1);
3595 
3596   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3597   if (mat->factorerrortype) {
3598     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3599     PetscCall(VecSetInf(x));
3600   } else PetscUseTypeMethod(mat, solve, b, x);
3601   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3602   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3603   PetscFunctionReturn(0);
3604 }
3605 
3606 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3607 {
3608   Vec      b, x;
3609   PetscInt N, i;
3610   PetscErrorCode (*f)(Mat, Vec, Vec);
3611   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3612 
3613   PetscFunctionBegin;
3614   if (A->factorerrortype) {
3615     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3616     PetscCall(MatSetInf(X));
3617     PetscFunctionReturn(0);
3618   }
3619   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3620   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3621   PetscCall(MatBoundToCPU(A, &Abound));
3622   if (!Abound) {
3623     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3624     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3625   }
3626 #if defined(PETSC_HAVE_CUDA)
3627   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3628   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3629 #elif (PETSC_HAVE_HIP)
3630   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3631   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3632 #endif
3633   PetscCall(MatGetSize(B, NULL, &N));
3634   for (i = 0; i < N; i++) {
3635     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3636     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3637     PetscCall((*f)(A, b, x));
3638     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3639     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3640   }
3641   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3642   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3643   PetscFunctionReturn(0);
3644 }
3645 
3646 /*@
3647    MatMatSolve - Solves A X = B, given a factored matrix.
3648 
3649    Neighbor-wise Collective on A
3650 
3651    Input Parameters:
3652 +  A - the factored matrix
3653 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3654 
3655    Output Parameter:
3656 .  X - the result matrix (dense matrix)
3657 
3658    Note:
3659    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3660    otherwise, B and X cannot be the same.
3661 
3662    Level: developer
3663 
3664 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3665 @*/
3666 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3667 {
3668   PetscFunctionBegin;
3669   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3670   PetscValidType(A, 1);
3671   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3672   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3673   PetscCheckSameComm(A, 1, B, 2);
3674   PetscCheckSameComm(A, 1, X, 3);
3675   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3676   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3677   PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3678   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3679   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3680   MatCheckPreallocated(A, 1);
3681 
3682   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3683   if (!A->ops->matsolve) {
3684     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3685     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3686   } else PetscUseTypeMethod(A, matsolve, B, X);
3687   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3688   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3689   PetscFunctionReturn(0);
3690 }
3691 
3692 /*@
3693    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3694 
3695    Neighbor-wise Collective on A
3696 
3697    Input Parameters:
3698 +  A - the factored matrix
3699 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3700 
3701    Output Parameter:
3702 .  X - the result matrix (dense matrix)
3703 
3704    Note:
3705    The matrices B and X cannot be the same.  I.e., one cannot
3706    call `MatMatSolveTranspose`(A,X,X).
3707 
3708    Level: developer
3709 
3710 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3711 @*/
3712 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3713 {
3714   PetscFunctionBegin;
3715   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3716   PetscValidType(A, 1);
3717   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3718   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3719   PetscCheckSameComm(A, 1, B, 2);
3720   PetscCheckSameComm(A, 1, X, 3);
3721   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3722   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3723   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3724   PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n);
3725   PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3726   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3727   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3728   MatCheckPreallocated(A, 1);
3729 
3730   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3731   if (!A->ops->matsolvetranspose) {
3732     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3733     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3734   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3735   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3736   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3737   PetscFunctionReturn(0);
3738 }
3739 
3740 /*@
3741    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3742 
3743    Neighbor-wise Collective on A
3744 
3745    Input Parameters:
3746 +  A - the factored matrix
3747 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3748 
3749    Output Parameter:
3750 .  X - the result matrix (dense matrix)
3751 
3752    Note:
3753    For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row
3754    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3755 
3756    Level: developer
3757 
3758 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3759 @*/
3760 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3761 {
3762   PetscFunctionBegin;
3763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3764   PetscValidType(A, 1);
3765   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3766   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3767   PetscCheckSameComm(A, 1, Bt, 2);
3768   PetscCheckSameComm(A, 1, X, 3);
3769 
3770   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3771   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3772   PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N);
3773   PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix");
3774   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3775   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3776   MatCheckPreallocated(A, 1);
3777 
3778   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3779   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3780   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3781   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3782   PetscFunctionReturn(0);
3783 }
3784 
3785 /*@
3786    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3787                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3788 
3789    Neighbor-wise Collective
3790 
3791    Input Parameters:
3792 +  mat - the factored matrix
3793 -  b - the right-hand-side vector
3794 
3795    Output Parameter:
3796 .  x - the result vector
3797 
3798    Notes:
3799    `MatSolve()` should be used for most applications, as it performs
3800    a forward solve followed by a backward solve.
3801 
3802    The vectors b and x cannot be the same,  i.e., one cannot
3803    call `MatForwardSolve`(A,x,x).
3804 
3805    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3806    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3807    `MatForwardSolve()` solves U^T*D y = b, and
3808    `MatBackwardSolve()` solves U x = y.
3809    Thus they do not provide a symmetric preconditioner.
3810 
3811    Level: developer
3812 
3813 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3814 @*/
3815 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3816 {
3817   PetscFunctionBegin;
3818   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3819   PetscValidType(mat, 1);
3820   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3821   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3822   PetscCheckSameComm(mat, 1, b, 2);
3823   PetscCheckSameComm(mat, 1, x, 3);
3824   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3825   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3826   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3827   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3828   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3829   MatCheckPreallocated(mat, 1);
3830 
3831   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3832   PetscUseTypeMethod(mat, forwardsolve, b, x);
3833   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3834   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3835   PetscFunctionReturn(0);
3836 }
3837 
3838 /*@
3839    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3840                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3841 
3842    Neighbor-wise Collective
3843 
3844    Input Parameters:
3845 +  mat - the factored matrix
3846 -  b - the right-hand-side vector
3847 
3848    Output Parameter:
3849 .  x - the result vector
3850 
3851    Notes:
3852    `MatSolve()` should be used for most applications, as it performs
3853    a forward solve followed by a backward solve.
3854 
3855    The vectors b and x cannot be the same.  I.e., one cannot
3856    call `MatBackwardSolve`(A,x,x).
3857 
3858    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3859    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3860    `MatForwardSolve()` solves U^T*D y = b, and
3861    `MatBackwardSolve()` solves U x = y.
3862    Thus they do not provide a symmetric preconditioner.
3863 
3864    Level: developer
3865 
3866 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3867 @*/
3868 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3869 {
3870   PetscFunctionBegin;
3871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3872   PetscValidType(mat, 1);
3873   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3874   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3875   PetscCheckSameComm(mat, 1, b, 2);
3876   PetscCheckSameComm(mat, 1, x, 3);
3877   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3878   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3879   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3880   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3881   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3882   MatCheckPreallocated(mat, 1);
3883 
3884   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3885   PetscUseTypeMethod(mat, backwardsolve, b, x);
3886   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3887   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3888   PetscFunctionReturn(0);
3889 }
3890 
3891 /*@
3892    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3893 
3894    Neighbor-wise Collective
3895 
3896    Input Parameters:
3897 +  mat - the factored matrix
3898 .  b - the right-hand-side vector
3899 -  y - the vector to be added to
3900 
3901    Output Parameter:
3902 .  x - the result vector
3903 
3904    Note:
3905    The vectors b and x cannot be the same.  I.e., one cannot
3906    call `MatSolveAdd`(A,x,y,x).
3907 
3908    Level: developer
3909 
3910 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3911 @*/
3912 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3913 {
3914   PetscScalar one = 1.0;
3915   Vec         tmp;
3916 
3917   PetscFunctionBegin;
3918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3919   PetscValidType(mat, 1);
3920   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3921   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3922   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3923   PetscCheckSameComm(mat, 1, b, 2);
3924   PetscCheckSameComm(mat, 1, y, 3);
3925   PetscCheckSameComm(mat, 1, x, 4);
3926   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3927   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3928   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3929   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
3930   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3931   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
3932   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3933   MatCheckPreallocated(mat, 1);
3934 
3935   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3936   if (mat->factorerrortype) {
3937     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3938     PetscCall(VecSetInf(x));
3939   } else if (mat->ops->solveadd) {
3940     PetscUseTypeMethod(mat, solveadd, b, y, x);
3941   } else {
3942     /* do the solve then the add manually */
3943     if (x != y) {
3944       PetscCall(MatSolve(mat, b, x));
3945       PetscCall(VecAXPY(x, one, y));
3946     } else {
3947       PetscCall(VecDuplicate(x, &tmp));
3948       PetscCall(VecCopy(x, tmp));
3949       PetscCall(MatSolve(mat, b, x));
3950       PetscCall(VecAXPY(x, one, tmp));
3951       PetscCall(VecDestroy(&tmp));
3952     }
3953   }
3954   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3955   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3956   PetscFunctionReturn(0);
3957 }
3958 
3959 /*@
3960    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3961 
3962    Neighbor-wise Collective
3963 
3964    Input Parameters:
3965 +  mat - the factored matrix
3966 -  b - the right-hand-side vector
3967 
3968    Output Parameter:
3969 .  x - the result vector
3970 
3971    Notes:
3972    The vectors b and x cannot be the same.  I.e., one cannot
3973    call `MatSolveTranspose`(A,x,x).
3974 
3975    Most users should employ the `KSP` interface for linear solvers
3976    instead of working directly with matrix algebra routines such as this.
3977    See, e.g., `KSPCreate()`.
3978 
3979    Level: developer
3980 
3981 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3982 @*/
3983 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3984 {
3985   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3986 
3987   PetscFunctionBegin;
3988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3989   PetscValidType(mat, 1);
3990   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3991   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3992   PetscCheckSameComm(mat, 1, b, 2);
3993   PetscCheckSameComm(mat, 1, x, 3);
3994   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3995   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
3996   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
3997   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3998   MatCheckPreallocated(mat, 1);
3999   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4000   if (mat->factorerrortype) {
4001     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4002     PetscCall(VecSetInf(x));
4003   } else {
4004     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4005     PetscCall((*f)(mat, b, x));
4006   }
4007   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4008   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4009   PetscFunctionReturn(0);
4010 }
4011 
4012 /*@
4013    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4014                       factored matrix.
4015 
4016    Neighbor-wise Collective
4017 
4018    Input Parameters:
4019 +  mat - the factored matrix
4020 .  b - the right-hand-side vector
4021 -  y - the vector to be added to
4022 
4023    Output Parameter:
4024 .  x - the result vector
4025 
4026    Note:
4027    The vectors b and x cannot be the same.  I.e., one cannot
4028    call `MatSolveTransposeAdd`(A,x,y,x).
4029 
4030    Level: developer
4031 
4032 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4033 @*/
4034 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4035 {
4036   PetscScalar one = 1.0;
4037   Vec         tmp;
4038   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4039 
4040   PetscFunctionBegin;
4041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4042   PetscValidType(mat, 1);
4043   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4044   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4045   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4046   PetscCheckSameComm(mat, 1, b, 2);
4047   PetscCheckSameComm(mat, 1, y, 3);
4048   PetscCheckSameComm(mat, 1, x, 4);
4049   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4050   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4051   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4052   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
4053   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
4054   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4055   MatCheckPreallocated(mat, 1);
4056 
4057   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4058   if (mat->factorerrortype) {
4059     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4060     PetscCall(VecSetInf(x));
4061   } else if (f) {
4062     PetscCall((*f)(mat, b, y, x));
4063   } else {
4064     /* do the solve then the add manually */
4065     if (x != y) {
4066       PetscCall(MatSolveTranspose(mat, b, x));
4067       PetscCall(VecAXPY(x, one, y));
4068     } else {
4069       PetscCall(VecDuplicate(x, &tmp));
4070       PetscCall(VecCopy(x, tmp));
4071       PetscCall(MatSolveTranspose(mat, b, x));
4072       PetscCall(VecAXPY(x, one, tmp));
4073       PetscCall(VecDestroy(&tmp));
4074     }
4075   }
4076   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4077   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4078   PetscFunctionReturn(0);
4079 }
4080 /* ----------------------------------------------------------------*/
4081 
4082 /*@
4083    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4084 
4085    Neighbor-wise Collective
4086 
4087    Input Parameters:
4088 +  mat - the matrix
4089 .  b - the right hand side
4090 .  omega - the relaxation factor
4091 .  flag - flag indicating the type of SOR (see below)
4092 .  shift -  diagonal shift
4093 .  its - the number of iterations
4094 -  lits - the number of local iterations
4095 
4096    Output Parameter:
4097 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4098 
4099    SOR Flags:
4100 +     `SOR_FORWARD_SWEEP` - forward SOR
4101 .     `SOR_BACKWARD_SWEEP` - backward SOR
4102 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4103 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4104 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4105 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4106 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4107 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4108          upper/lower triangular part of matrix to
4109          vector (with omega)
4110 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4111 
4112    Notes:
4113    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4114    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4115    on each processor.
4116 
4117    Application programmers will not generally use `MatSOR()` directly,
4118    but instead will employ the `KSP`/`PC` interface.
4119 
4120    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4121 
4122    Most users should employ the `KSP` interface for linear solvers
4123    instead of working directly with matrix algebra routines such as this.
4124    See, e.g., `KSPCreate()`.
4125 
4126    Vectors x and b CANNOT be the same
4127 
4128    Notes for Advanced Users:
4129    The flags are implemented as bitwise inclusive or operations.
4130    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4131    to specify a zero initial guess for SSOR.
4132 
4133    Developer Note:
4134    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4135 
4136    Level: developer
4137 
4138 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4139 @*/
4140 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4141 {
4142   PetscFunctionBegin;
4143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4144   PetscValidType(mat, 1);
4145   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4146   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4147   PetscCheckSameComm(mat, 1, b, 2);
4148   PetscCheckSameComm(mat, 1, x, 8);
4149   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4150   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4151   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
4152   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
4153   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
4154   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4155   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4156   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4157 
4158   MatCheckPreallocated(mat, 1);
4159   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4160   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4161   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4162   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4163   PetscFunctionReturn(0);
4164 }
4165 
4166 /*
4167       Default matrix copy routine.
4168 */
4169 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4170 {
4171   PetscInt           i, rstart = 0, rend = 0, nz;
4172   const PetscInt    *cwork;
4173   const PetscScalar *vwork;
4174 
4175   PetscFunctionBegin;
4176   if (B->assembled) PetscCall(MatZeroEntries(B));
4177   if (str == SAME_NONZERO_PATTERN) {
4178     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4179     for (i = rstart; i < rend; i++) {
4180       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4181       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4182       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4183     }
4184   } else {
4185     PetscCall(MatAYPX(B, 0.0, A, str));
4186   }
4187   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4188   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4189   PetscFunctionReturn(0);
4190 }
4191 
4192 /*@
4193    MatCopy - Copies a matrix to another matrix.
4194 
4195    Collective on A
4196 
4197    Input Parameters:
4198 +  A - the matrix
4199 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4200 
4201    Output Parameter:
4202 .  B - where the copy is put
4203 
4204    Notes:
4205    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4206 
4207    `MatCopy()` copies the matrix entries of a matrix to another existing
4208    matrix (after first zeroing the second matrix).  A related routine is
4209    `MatConvert()`, which first creates a new matrix and then copies the data.
4210 
4211    Level: intermediate
4212 
4213 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4214 @*/
4215 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4216 {
4217   PetscInt i;
4218 
4219   PetscFunctionBegin;
4220   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4221   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4222   PetscValidType(A, 1);
4223   PetscValidType(B, 2);
4224   PetscCheckSameComm(A, 1, B, 2);
4225   MatCheckPreallocated(B, 2);
4226   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4227   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4228   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N,
4229              A->cmap->N, B->cmap->N);
4230   MatCheckPreallocated(A, 1);
4231   if (A == B) PetscFunctionReturn(0);
4232 
4233   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4234   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4235   else PetscCall(MatCopy_Basic(A, B, str));
4236 
4237   B->stencil.dim = A->stencil.dim;
4238   B->stencil.noc = A->stencil.noc;
4239   for (i = 0; i <= A->stencil.dim; i++) {
4240     B->stencil.dims[i]   = A->stencil.dims[i];
4241     B->stencil.starts[i] = A->stencil.starts[i];
4242   }
4243 
4244   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4245   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4246   PetscFunctionReturn(0);
4247 }
4248 
4249 /*@C
4250    MatConvert - Converts a matrix to another matrix, either of the same
4251    or different type.
4252 
4253    Collective
4254 
4255    Input Parameters:
4256 +  mat - the matrix
4257 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4258    same type as the original matrix.
4259 -  reuse - denotes if the destination matrix is to be created or reused.
4260    Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4261    `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused).
4262 
4263    Output Parameter:
4264 .  M - pointer to place new matrix
4265 
4266    Notes:
4267    `MatConvert()` first creates a new matrix and then copies the data from
4268    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4269    entries of one matrix to another already existing matrix context.
4270 
4271    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4272    the MPI communicator of the generated matrix is always the same as the communicator
4273    of the input matrix.
4274 
4275    Level: intermediate
4276 
4277 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4278 @*/
4279 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4280 {
4281   PetscBool  sametype, issame, flg;
4282   PetscBool3 issymmetric, ishermitian;
4283   char       convname[256], mtype[256];
4284   Mat        B;
4285 
4286   PetscFunctionBegin;
4287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4288   PetscValidType(mat, 1);
4289   PetscValidPointer(M, 4);
4290   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4291   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4292   MatCheckPreallocated(mat, 1);
4293 
4294   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4295   if (flg) newtype = mtype;
4296 
4297   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4298   PetscCall(PetscStrcmp(newtype, "same", &issame));
4299   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4300   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4301 
4302   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4303     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4304     PetscFunctionReturn(0);
4305   }
4306 
4307   /* Cache Mat options because some converters use MatHeaderReplace  */
4308   issymmetric = mat->symmetric;
4309   ishermitian = mat->hermitian;
4310 
4311   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4312     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4313     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4314   } else {
4315     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4316     const char *prefix[3]                                 = {"seq", "mpi", ""};
4317     PetscInt    i;
4318     /*
4319        Order of precedence:
4320        0) See if newtype is a superclass of the current matrix.
4321        1) See if a specialized converter is known to the current matrix.
4322        2) See if a specialized converter is known to the desired matrix class.
4323        3) See if a good general converter is registered for the desired class
4324           (as of 6/27/03 only MATMPIADJ falls into this category).
4325        4) See if a good general converter is known for the current matrix.
4326        5) Use a really basic converter.
4327     */
4328 
4329     /* 0) See if newtype is a superclass of the current matrix.
4330           i.e mat is mpiaij and newtype is aij */
4331     for (i = 0; i < 2; i++) {
4332       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4333       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4334       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4335       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4336       if (flg) {
4337         if (reuse == MAT_INPLACE_MATRIX) {
4338           PetscCall(PetscInfo(mat, "Early return\n"));
4339           PetscFunctionReturn(0);
4340         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4341           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4342           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4343           PetscFunctionReturn(0);
4344         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4345           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4346           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4347           PetscFunctionReturn(0);
4348         }
4349       }
4350     }
4351     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4352     for (i = 0; i < 3; i++) {
4353       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4354       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4355       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4357       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4358       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4359       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4360       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4361       if (conv) goto foundconv;
4362     }
4363 
4364     /* 2)  See if a specialized converter is known to the desired matrix class. */
4365     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4366     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4367     PetscCall(MatSetType(B, newtype));
4368     for (i = 0; i < 3; i++) {
4369       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4370       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4371       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4372       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4375       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4376       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4377       if (conv) {
4378         PetscCall(MatDestroy(&B));
4379         goto foundconv;
4380       }
4381     }
4382 
4383     /* 3) See if a good general converter is registered for the desired class */
4384     conv = B->ops->convertfrom;
4385     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4386     PetscCall(MatDestroy(&B));
4387     if (conv) goto foundconv;
4388 
4389     /* 4) See if a good general converter is known for the current matrix */
4390     if (mat->ops->convert) conv = mat->ops->convert;
4391     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4392     if (conv) goto foundconv;
4393 
4394     /* 5) Use a really basic converter. */
4395     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4396     conv = MatConvert_Basic;
4397 
4398   foundconv:
4399     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4400     PetscCall((*conv)(mat, newtype, reuse, M));
4401     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4402       /* the block sizes must be same if the mappings are copied over */
4403       (*M)->rmap->bs = mat->rmap->bs;
4404       (*M)->cmap->bs = mat->cmap->bs;
4405       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4406       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4407       (*M)->rmap->mapping = mat->rmap->mapping;
4408       (*M)->cmap->mapping = mat->cmap->mapping;
4409     }
4410     (*M)->stencil.dim = mat->stencil.dim;
4411     (*M)->stencil.noc = mat->stencil.noc;
4412     for (i = 0; i <= mat->stencil.dim; i++) {
4413       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4414       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4415     }
4416     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4417   }
4418   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4419 
4420   /* Copy Mat options */
4421   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4422   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4423   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4424   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4425   PetscFunctionReturn(0);
4426 }
4427 
4428 /*@C
4429    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4430 
4431    Not Collective
4432 
4433    Input Parameter:
4434 .  mat - the matrix, must be a factored matrix
4435 
4436    Output Parameter:
4437 .   type - the string name of the package (do not free this string)
4438 
4439    Level: intermediate
4440 
4441    Note:
4442       In Fortran you pass in a empty string and the package name will be copied into it.
4443     (Make sure the string is long enough)
4444 
4445 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4446 @*/
4447 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4448 {
4449   PetscErrorCode (*conv)(Mat, MatSolverType *);
4450 
4451   PetscFunctionBegin;
4452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4453   PetscValidType(mat, 1);
4454   PetscValidPointer(type, 2);
4455   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4456   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4457   if (conv) PetscCall((*conv)(mat, type));
4458   else *type = MATSOLVERPETSC;
4459   PetscFunctionReturn(0);
4460 }
4461 
4462 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4463 struct _MatSolverTypeForSpecifcType {
4464   MatType mtype;
4465   /* no entry for MAT_FACTOR_NONE */
4466   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4467   MatSolverTypeForSpecifcType next;
4468 };
4469 
4470 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4471 struct _MatSolverTypeHolder {
4472   char                       *name;
4473   MatSolverTypeForSpecifcType handlers;
4474   MatSolverTypeHolder         next;
4475 };
4476 
4477 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4478 
4479 /*@C
4480    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4481 
4482    Input Parameters:
4483 +    package - name of the package, for example petsc or superlu
4484 .    mtype - the matrix type that works with this package
4485 .    ftype - the type of factorization supported by the package
4486 -    createfactor - routine that will create the factored matrix ready to be used
4487 
4488     Level: developer
4489 
4490 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4491 @*/
4492 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4493 {
4494   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4495   PetscBool                   flg;
4496   MatSolverTypeForSpecifcType inext, iprev = NULL;
4497 
4498   PetscFunctionBegin;
4499   PetscCall(MatInitializePackage());
4500   if (!next) {
4501     PetscCall(PetscNew(&MatSolverTypeHolders));
4502     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4503     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4504     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4505     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4506     PetscFunctionReturn(0);
4507   }
4508   while (next) {
4509     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4510     if (flg) {
4511       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4512       inext = next->handlers;
4513       while (inext) {
4514         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4515         if (flg) {
4516           inext->createfactor[(int)ftype - 1] = createfactor;
4517           PetscFunctionReturn(0);
4518         }
4519         iprev = inext;
4520         inext = inext->next;
4521       }
4522       PetscCall(PetscNew(&iprev->next));
4523       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4524       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4525       PetscFunctionReturn(0);
4526     }
4527     prev = next;
4528     next = next->next;
4529   }
4530   PetscCall(PetscNew(&prev->next));
4531   PetscCall(PetscStrallocpy(package, &prev->next->name));
4532   PetscCall(PetscNew(&prev->next->handlers));
4533   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4534   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4535   PetscFunctionReturn(0);
4536 }
4537 
4538 /*@C
4539    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4540 
4541    Input Parameters:
4542 +    type - name of the package, for example petsc or superlu
4543 .    ftype - the type of factorization supported by the type
4544 -    mtype - the matrix type that works with this type
4545 
4546    Output Parameters:
4547 +   foundtype - `PETSC_TRUE` if the type was registered
4548 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4549 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4550 
4551     Level: developer
4552 
4553 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4554 @*/
4555 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4556 {
4557   MatSolverTypeHolder         next = MatSolverTypeHolders;
4558   PetscBool                   flg;
4559   MatSolverTypeForSpecifcType inext;
4560 
4561   PetscFunctionBegin;
4562   if (foundtype) *foundtype = PETSC_FALSE;
4563   if (foundmtype) *foundmtype = PETSC_FALSE;
4564   if (createfactor) *createfactor = NULL;
4565 
4566   if (type) {
4567     while (next) {
4568       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4569       if (flg) {
4570         if (foundtype) *foundtype = PETSC_TRUE;
4571         inext = next->handlers;
4572         while (inext) {
4573           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4574           if (flg) {
4575             if (foundmtype) *foundmtype = PETSC_TRUE;
4576             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4577             PetscFunctionReturn(0);
4578           }
4579           inext = inext->next;
4580         }
4581       }
4582       next = next->next;
4583     }
4584   } else {
4585     while (next) {
4586       inext = next->handlers;
4587       while (inext) {
4588         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4589         if (flg && inext->createfactor[(int)ftype - 1]) {
4590           if (foundtype) *foundtype = PETSC_TRUE;
4591           if (foundmtype) *foundmtype = PETSC_TRUE;
4592           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4593           PetscFunctionReturn(0);
4594         }
4595         inext = inext->next;
4596       }
4597       next = next->next;
4598     }
4599     /* try with base classes inext->mtype */
4600     next = MatSolverTypeHolders;
4601     while (next) {
4602       inext = next->handlers;
4603       while (inext) {
4604         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4605         if (flg && inext->createfactor[(int)ftype - 1]) {
4606           if (foundtype) *foundtype = PETSC_TRUE;
4607           if (foundmtype) *foundmtype = PETSC_TRUE;
4608           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4609           PetscFunctionReturn(0);
4610         }
4611         inext = inext->next;
4612       }
4613       next = next->next;
4614     }
4615   }
4616   PetscFunctionReturn(0);
4617 }
4618 
4619 PetscErrorCode MatSolverTypeDestroy(void)
4620 {
4621   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4622   MatSolverTypeForSpecifcType inext, iprev;
4623 
4624   PetscFunctionBegin;
4625   while (next) {
4626     PetscCall(PetscFree(next->name));
4627     inext = next->handlers;
4628     while (inext) {
4629       PetscCall(PetscFree(inext->mtype));
4630       iprev = inext;
4631       inext = inext->next;
4632       PetscCall(PetscFree(iprev));
4633     }
4634     prev = next;
4635     next = next->next;
4636     PetscCall(PetscFree(prev));
4637   }
4638   MatSolverTypeHolders = NULL;
4639   PetscFunctionReturn(0);
4640 }
4641 
4642 /*@C
4643    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4644 
4645    Logically Collective
4646 
4647    Input Parameters:
4648 .  mat - the matrix
4649 
4650    Output Parameters:
4651 .  flg - `PETSC_TRUE` if uses the ordering
4652 
4653    Note:
4654    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4655    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4656 
4657    Level: developer
4658 
4659 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4660 @*/
4661 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4662 {
4663   PetscFunctionBegin;
4664   *flg = mat->canuseordering;
4665   PetscFunctionReturn(0);
4666 }
4667 
4668 /*@C
4669    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4670 
4671    Logically Collective
4672 
4673    Input Parameters:
4674 .  mat - the matrix obtained with `MatGetFactor()`
4675 
4676    Output Parameters:
4677 .  otype - the preferred type
4678 
4679    Level: developer
4680 
4681 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4682 @*/
4683 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4684 {
4685   PetscFunctionBegin;
4686   *otype = mat->preferredordering[ftype];
4687   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4688   PetscFunctionReturn(0);
4689 }
4690 
4691 /*@C
4692    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4693 
4694    Collective
4695 
4696    Input Parameters:
4697 +  mat - the matrix
4698 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4699 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4700 
4701    Output Parameters:
4702 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4703 
4704    Options Database Key:
4705 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4706                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4707 
4708    Notes:
4709      Users usually access the factorization solvers via `KSP`
4710 
4711       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4712      such as pastix, superlu, mumps etc.
4713 
4714       PETSc must have been ./configure to use the external solver, using the option --download-package
4715 
4716       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4717       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4718       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4719 
4720    Developer Note:
4721       This should actually be called `MatCreateFactor()` since it creates a new factor object
4722 
4723    Level: intermediate
4724 
4725 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4726           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4727 @*/
4728 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4729 {
4730   PetscBool foundtype, foundmtype;
4731   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4732 
4733   PetscFunctionBegin;
4734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4735   PetscValidType(mat, 1);
4736 
4737   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4738   MatCheckPreallocated(mat, 1);
4739 
4740   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4741   if (!foundtype) {
4742     if (type) {
4743       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype],
4744               ((PetscObject)mat)->type_name, type);
4745     } else {
4746       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4747     }
4748   }
4749   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4750   PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name);
4751 
4752   PetscCall((*conv)(mat, ftype, f));
4753   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4754   PetscFunctionReturn(0);
4755 }
4756 
4757 /*@C
4758    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4759 
4760    Not Collective
4761 
4762    Input Parameters:
4763 +  mat - the matrix
4764 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4765 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4766 
4767    Output Parameter:
4768 .    flg - PETSC_TRUE if the factorization is available
4769 
4770    Notes:
4771       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4772      such as pastix, superlu, mumps etc.
4773 
4774       PETSc must have been ./configure to use the external solver, using the option --download-package
4775 
4776    Developer Note:
4777       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4778 
4779    Level: intermediate
4780 
4781 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4782           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4783 @*/
4784 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4785 {
4786   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4787 
4788   PetscFunctionBegin;
4789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4790   PetscValidType(mat, 1);
4791   PetscValidBoolPointer(flg, 4);
4792 
4793   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4794   MatCheckPreallocated(mat, 1);
4795 
4796   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4797   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4798   PetscFunctionReturn(0);
4799 }
4800 
4801 /*@
4802    MatDuplicate - Duplicates a matrix including the non-zero structure.
4803 
4804    Collective
4805 
4806    Input Parameters:
4807 +  mat - the matrix
4808 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4809         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4810 
4811    Output Parameter:
4812 .  M - pointer to place new matrix
4813 
4814    Level: intermediate
4815 
4816    Notes:
4817     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4818 
4819     May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well.
4820 
4821     When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat
4822     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4823     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4824 
4825 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4826 @*/
4827 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4828 {
4829   Mat         B;
4830   VecType     vtype;
4831   PetscInt    i;
4832   PetscObject dm;
4833   void (*viewf)(void);
4834 
4835   PetscFunctionBegin;
4836   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4837   PetscValidType(mat, 1);
4838   PetscValidPointer(M, 3);
4839   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4840   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4841   MatCheckPreallocated(mat, 1);
4842 
4843   *M = NULL;
4844   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4845   PetscUseTypeMethod(mat, duplicate, op, M);
4846   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4847   B = *M;
4848 
4849   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4850   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4851   PetscCall(MatGetVecType(mat, &vtype));
4852   PetscCall(MatSetVecType(B, vtype));
4853 
4854   B->stencil.dim = mat->stencil.dim;
4855   B->stencil.noc = mat->stencil.noc;
4856   for (i = 0; i <= mat->stencil.dim; i++) {
4857     B->stencil.dims[i]   = mat->stencil.dims[i];
4858     B->stencil.starts[i] = mat->stencil.starts[i];
4859   }
4860 
4861   B->nooffproczerorows = mat->nooffproczerorows;
4862   B->nooffprocentries  = mat->nooffprocentries;
4863 
4864   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4865   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4866   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4867   PetscFunctionReturn(0);
4868 }
4869 
4870 /*@
4871    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4872 
4873    Logically Collective
4874 
4875    Input Parameters:
4876 +  mat - the matrix
4877 -  v - the vector for storing the diagonal
4878 
4879    Output Parameter:
4880 .  v - the diagonal of the matrix
4881 
4882    Level: intermediate
4883 
4884    Note:
4885    Currently only correct in parallel for square matrices.
4886 
4887 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4888 @*/
4889 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4890 {
4891   PetscFunctionBegin;
4892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4893   PetscValidType(mat, 1);
4894   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4895   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4896   MatCheckPreallocated(mat, 1);
4897 
4898   PetscUseTypeMethod(mat, getdiagonal, v);
4899   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4900   PetscFunctionReturn(0);
4901 }
4902 
4903 /*@C
4904    MatGetRowMin - Gets the minimum value (of the real part) of each
4905         row of the matrix
4906 
4907    Logically Collective
4908 
4909    Input Parameter:
4910 .  mat - the matrix
4911 
4912    Output Parameters:
4913 +  v - the vector for storing the maximums
4914 -  idx - the indices of the column found for each row (optional)
4915 
4916    Level: intermediate
4917 
4918    Note:
4919     The result of this call are the same as if one converted the matrix to dense format
4920       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4921 
4922     This code is only implemented for a couple of matrix formats.
4923 
4924 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4925           `MatGetRowMax()`
4926 @*/
4927 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4928 {
4929   PetscFunctionBegin;
4930   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4931   PetscValidType(mat, 1);
4932   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4933   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4934 
4935   if (!mat->cmap->N) {
4936     PetscCall(VecSet(v, PETSC_MAX_REAL));
4937     if (idx) {
4938       PetscInt i, m = mat->rmap->n;
4939       for (i = 0; i < m; i++) idx[i] = -1;
4940     }
4941   } else {
4942     MatCheckPreallocated(mat, 1);
4943   }
4944   PetscUseTypeMethod(mat, getrowmin, v, idx);
4945   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4946   PetscFunctionReturn(0);
4947 }
4948 
4949 /*@C
4950    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4951         row of the matrix
4952 
4953    Logically Collective
4954 
4955    Input Parameter:
4956 .  mat - the matrix
4957 
4958    Output Parameters:
4959 +  v - the vector for storing the minimums
4960 -  idx - the indices of the column found for each row (or NULL if not needed)
4961 
4962    Level: intermediate
4963 
4964    Notes:
4965     if a row is completely empty or has only 0.0 values then the idx[] value for that
4966     row is 0 (the first column).
4967 
4968     This code is only implemented for a couple of matrix formats.
4969 
4970 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4971 @*/
4972 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4973 {
4974   PetscFunctionBegin;
4975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4976   PetscValidType(mat, 1);
4977   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4978   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4979   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4980 
4981   if (!mat->cmap->N) {
4982     PetscCall(VecSet(v, 0.0));
4983     if (idx) {
4984       PetscInt i, m = mat->rmap->n;
4985       for (i = 0; i < m; i++) idx[i] = -1;
4986     }
4987   } else {
4988     MatCheckPreallocated(mat, 1);
4989     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4990     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4991   }
4992   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4993   PetscFunctionReturn(0);
4994 }
4995 
4996 /*@C
4997    MatGetRowMax - Gets the maximum value (of the real part) of each
4998         row of the matrix
4999 
5000    Logically Collective
5001 
5002    Input Parameter:
5003 .  mat - the matrix
5004 
5005    Output Parameters:
5006 +  v - the vector for storing the maximums
5007 -  idx - the indices of the column found for each row (optional)
5008 
5009    Level: intermediate
5010 
5011    Notes:
5012     The result of this call are the same as if one converted the matrix to dense format
5013       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5014 
5015     This code is only implemented for a couple of matrix formats.
5016 
5017 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5018 @*/
5019 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5020 {
5021   PetscFunctionBegin;
5022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5023   PetscValidType(mat, 1);
5024   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5025   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5026 
5027   if (!mat->cmap->N) {
5028     PetscCall(VecSet(v, PETSC_MIN_REAL));
5029     if (idx) {
5030       PetscInt i, m = mat->rmap->n;
5031       for (i = 0; i < m; i++) idx[i] = -1;
5032     }
5033   } else {
5034     MatCheckPreallocated(mat, 1);
5035     PetscUseTypeMethod(mat, getrowmax, v, idx);
5036   }
5037   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5038   PetscFunctionReturn(0);
5039 }
5040 
5041 /*@C
5042    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5043         row of the matrix
5044 
5045    Logically Collective
5046 
5047    Input Parameter:
5048 .  mat - the matrix
5049 
5050    Output Parameters:
5051 +  v - the vector for storing the maximums
5052 -  idx - the indices of the column found for each row (or NULL if not needed)
5053 
5054    Level: intermediate
5055 
5056    Notes:
5057     if a row is completely empty or has only 0.0 values then the idx[] value for that
5058     row is 0 (the first column).
5059 
5060     This code is only implemented for a couple of matrix formats.
5061 
5062 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5063 @*/
5064 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5065 {
5066   PetscFunctionBegin;
5067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5068   PetscValidType(mat, 1);
5069   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5071 
5072   if (!mat->cmap->N) {
5073     PetscCall(VecSet(v, 0.0));
5074     if (idx) {
5075       PetscInt i, m = mat->rmap->n;
5076       for (i = 0; i < m; i++) idx[i] = -1;
5077     }
5078   } else {
5079     MatCheckPreallocated(mat, 1);
5080     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5081     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5082   }
5083   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5084   PetscFunctionReturn(0);
5085 }
5086 
5087 /*@
5088    MatGetRowSum - Gets the sum of each row of the matrix
5089 
5090    Logically or Neighborhood Collective
5091 
5092    Input Parameters:
5093 .  mat - the matrix
5094 
5095    Output Parameter:
5096 .  v - the vector for storing the sum of rows
5097 
5098    Level: intermediate
5099 
5100    Notes:
5101     This code is slow since it is not currently specialized for different formats
5102 
5103 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5104 @*/
5105 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5106 {
5107   Vec ones;
5108 
5109   PetscFunctionBegin;
5110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5111   PetscValidType(mat, 1);
5112   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5113   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5114   MatCheckPreallocated(mat, 1);
5115   PetscCall(MatCreateVecs(mat, &ones, NULL));
5116   PetscCall(VecSet(ones, 1.));
5117   PetscCall(MatMult(mat, ones, v));
5118   PetscCall(VecDestroy(&ones));
5119   PetscFunctionReturn(0);
5120 }
5121 
5122 /*@
5123    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5124    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5125 
5126    Collective
5127 
5128    Input Parameter:
5129 .  mat - the matrix to provide the transpose
5130 
5131    Output Parameter:
5132 .  mat - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results
5133 
5134    Level: advanced
5135 
5136    Note:
5137    Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This
5138    routine allows bypassing that call.
5139 
5140 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5141 @*/
5142 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5143 {
5144   PetscContainer  rB = NULL;
5145   MatParentState *rb = NULL;
5146 
5147   PetscFunctionBegin;
5148   PetscCall(PetscNew(&rb));
5149   rb->id    = ((PetscObject)mat)->id;
5150   rb->state = 0;
5151   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5152   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5153   PetscCall(PetscContainerSetPointer(rB, rb));
5154   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5155   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5156   PetscCall(PetscObjectDereference((PetscObject)rB));
5157   PetscFunctionReturn(0);
5158 }
5159 
5160 /*@
5161    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5162 
5163    Collective
5164 
5165    Input Parameters:
5166 +  mat - the matrix to transpose
5167 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5168 
5169    Output Parameter:
5170 .  B - the transpose
5171 
5172    Notes:
5173      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5174 
5175      `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5176      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5177 
5178      If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types.
5179 
5180      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5181 
5182      If mat is unchanged from the last call this function returns immediately without recomputing the result
5183 
5184      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5185 
5186    Level: intermediate
5187 
5188 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5189           `MatTransposeSymbolic()`
5190 @*/
5191 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5192 {
5193   PetscContainer  rB = NULL;
5194   MatParentState *rb = NULL;
5195 
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5198   PetscValidType(mat, 1);
5199   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5200   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5201   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5202   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5203   MatCheckPreallocated(mat, 1);
5204   if (reuse == MAT_REUSE_MATRIX) {
5205     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5206     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5207     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5208     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5209     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5210   }
5211 
5212   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5213   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5214     PetscUseTypeMethod(mat, transpose, reuse, B);
5215     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5216   }
5217   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5218 
5219   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5220   if (reuse != MAT_INPLACE_MATRIX) {
5221     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5222     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5223     rb->state        = ((PetscObject)mat)->state;
5224     rb->nonzerostate = mat->nonzerostate;
5225   }
5226   PetscFunctionReturn(0);
5227 }
5228 
5229 /*@
5230    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5231 
5232    Collective on A
5233 
5234    Input Parameters:
5235 .  A - the matrix to transpose
5236 
5237    Output Parameter:
5238 .  B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the
5239       numerical portion.
5240 
5241    Level: intermediate
5242 
5243    Note:
5244    This is not supported for many matrix types, use `MatTranspose()` in those cases
5245 
5246 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5247 @*/
5248 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5249 {
5250   PetscFunctionBegin;
5251   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5252   PetscValidType(A, 1);
5253   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5254   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5255   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5256   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5257   PetscCall((*A->ops->transposesymbolic)(A, B));
5258   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5259 
5260   PetscCall(MatTransposeSetPrecursor(A, *B));
5261   PetscFunctionReturn(0);
5262 }
5263 
5264 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5265 {
5266   PetscContainer  rB;
5267   MatParentState *rb;
5268 
5269   PetscFunctionBegin;
5270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5271   PetscValidType(A, 1);
5272   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5273   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5274   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5275   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5276   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5277   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5278   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5279   PetscFunctionReturn(0);
5280 }
5281 
5282 /*@
5283    MatIsTranspose - Test whether a matrix is another one's transpose,
5284         or its own, in which case it tests symmetry.
5285 
5286    Collective on A
5287 
5288    Input Parameters:
5289 +  A - the matrix to test
5290 -  B - the matrix to test against, this can equal the first parameter
5291 
5292    Output Parameters:
5293 .  flg - the result
5294 
5295    Notes:
5296    Only available for `MATAIJ` matrices.
5297 
5298    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5299    test involves parallel copies of the block-offdiagonal parts of the matrix.
5300 
5301    Level: intermediate
5302 
5303 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5304 @*/
5305 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5306 {
5307   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5308 
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5311   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5312   PetscValidBoolPointer(flg, 4);
5313   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5314   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5315   *flg = PETSC_FALSE;
5316   if (f && g) {
5317     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5318     PetscCall((*f)(A, B, tol, flg));
5319   } else {
5320     MatType mattype;
5321 
5322     PetscCall(MatGetType(f ? B : A, &mattype));
5323     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5324   }
5325   PetscFunctionReturn(0);
5326 }
5327 
5328 /*@
5329    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5330 
5331    Collective
5332 
5333    Input Parameters:
5334 +  mat - the matrix to transpose and complex conjugate
5335 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5336 
5337    Output Parameter:
5338 .  B - the Hermitian transpose
5339 
5340    Level: intermediate
5341 
5342 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5343 @*/
5344 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5345 {
5346   PetscFunctionBegin;
5347   PetscCall(MatTranspose(mat, reuse, B));
5348 #if defined(PETSC_USE_COMPLEX)
5349   PetscCall(MatConjugate(*B));
5350 #endif
5351   PetscFunctionReturn(0);
5352 }
5353 
5354 /*@
5355    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5356 
5357    Collective on A
5358 
5359    Input Parameters:
5360 +  A - the matrix to test
5361 -  B - the matrix to test against, this can equal the first parameter
5362 
5363    Output Parameters:
5364 .  flg - the result
5365 
5366    Notes:
5367    Only available for `MATAIJ` matrices.
5368 
5369    The sequential algorithm
5370    has a running time of the order of the number of nonzeros; the parallel
5371    test involves parallel copies of the block-offdiagonal parts of the matrix.
5372 
5373    Level: intermediate
5374 
5375 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5376 @*/
5377 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5378 {
5379   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5380 
5381   PetscFunctionBegin;
5382   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5383   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5384   PetscValidBoolPointer(flg, 4);
5385   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5386   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5387   if (f && g) {
5388     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5389     PetscCall((*f)(A, B, tol, flg));
5390   }
5391   PetscFunctionReturn(0);
5392 }
5393 
5394 /*@
5395    MatPermute - Creates a new matrix with rows and columns permuted from the
5396    original.
5397 
5398    Collective
5399 
5400    Input Parameters:
5401 +  mat - the matrix to permute
5402 .  row - row permutation, each processor supplies only the permutation for its rows
5403 -  col - column permutation, each processor supplies only the permutation for its columns
5404 
5405    Output Parameters:
5406 .  B - the permuted matrix
5407 
5408    Level: advanced
5409 
5410    Note:
5411    The index sets map from row/col of permuted matrix to row/col of original matrix.
5412    The index sets should be on the same communicator as mat and have the same local sizes.
5413 
5414    Developer Note:
5415      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5416      exploit the fact that row and col are permutations, consider implementing the
5417      more general `MatCreateSubMatrix()` instead.
5418 
5419 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5420 @*/
5421 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5422 {
5423   PetscFunctionBegin;
5424   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5425   PetscValidType(mat, 1);
5426   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5427   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5428   PetscValidPointer(B, 4);
5429   PetscCheckSameComm(mat, 1, row, 2);
5430   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5433   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5434   MatCheckPreallocated(mat, 1);
5435 
5436   if (mat->ops->permute) {
5437     PetscUseTypeMethod(mat, permute, row, col, B);
5438     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5439   } else {
5440     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5441   }
5442   PetscFunctionReturn(0);
5443 }
5444 
5445 /*@
5446    MatEqual - Compares two matrices.
5447 
5448    Collective on A
5449 
5450    Input Parameters:
5451 +  A - the first matrix
5452 -  B - the second matrix
5453 
5454    Output Parameter:
5455 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5456 
5457    Level: intermediate
5458 
5459 .seealso: `Mat`
5460 @*/
5461 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5462 {
5463   PetscFunctionBegin;
5464   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5465   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5466   PetscValidType(A, 1);
5467   PetscValidType(B, 2);
5468   PetscValidBoolPointer(flg, 3);
5469   PetscCheckSameComm(A, 1, B, 2);
5470   MatCheckPreallocated(A, 1);
5471   MatCheckPreallocated(B, 2);
5472   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5473   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5474   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5475              B->cmap->N);
5476   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5477     PetscUseTypeMethod(A, equal, B, flg);
5478   } else {
5479     PetscCall(MatMultEqual(A, B, 10, flg));
5480   }
5481   PetscFunctionReturn(0);
5482 }
5483 
5484 /*@
5485    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5486    matrices that are stored as vectors.  Either of the two scaling
5487    matrices can be NULL.
5488 
5489    Collective
5490 
5491    Input Parameters:
5492 +  mat - the matrix to be scaled
5493 .  l - the left scaling vector (or NULL)
5494 -  r - the right scaling vector (or NULL)
5495 
5496    Note:
5497    `MatDiagonalScale()` computes A = LAR, where
5498    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5499    The L scales the rows of the matrix, the R scales the columns of the matrix.
5500 
5501    Level: intermediate
5502 
5503 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5504 @*/
5505 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5506 {
5507   PetscFunctionBegin;
5508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5509   PetscValidType(mat, 1);
5510   if (l) {
5511     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5512     PetscCheckSameComm(mat, 1, l, 2);
5513   }
5514   if (r) {
5515     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5516     PetscCheckSameComm(mat, 1, r, 3);
5517   }
5518   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5519   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5520   MatCheckPreallocated(mat, 1);
5521   if (!l && !r) PetscFunctionReturn(0);
5522 
5523   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5524   PetscUseTypeMethod(mat, diagonalscale, l, r);
5525   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5526   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5527   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5528   PetscFunctionReturn(0);
5529 }
5530 
5531 /*@
5532     MatScale - Scales all elements of a matrix by a given number.
5533 
5534     Logically Collective
5535 
5536     Input Parameters:
5537 +   mat - the matrix to be scaled
5538 -   a  - the scaling value
5539 
5540     Output Parameter:
5541 .   mat - the scaled matrix
5542 
5543     Level: intermediate
5544 
5545 .seealso: `Mat`, `MatDiagonalScale()`
5546 @*/
5547 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5548 {
5549   PetscFunctionBegin;
5550   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5551   PetscValidType(mat, 1);
5552   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5553   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5554   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5555   PetscValidLogicalCollectiveScalar(mat, a, 2);
5556   MatCheckPreallocated(mat, 1);
5557 
5558   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5559   if (a != (PetscScalar)1.0) {
5560     PetscUseTypeMethod(mat, scale, a);
5561     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5562   }
5563   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5564   PetscFunctionReturn(0);
5565 }
5566 
5567 /*@
5568    MatNorm - Calculates various norms of a matrix.
5569 
5570    Collective
5571 
5572    Input Parameters:
5573 +  mat - the matrix
5574 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5575 
5576    Output Parameter:
5577 .  nrm - the resulting norm
5578 
5579    Level: intermediate
5580 
5581 .seealso: `Mat`
5582 @*/
5583 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5584 {
5585   PetscFunctionBegin;
5586   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5587   PetscValidType(mat, 1);
5588   PetscValidRealPointer(nrm, 3);
5589 
5590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5592   MatCheckPreallocated(mat, 1);
5593 
5594   PetscUseTypeMethod(mat, norm, type, nrm);
5595   PetscFunctionReturn(0);
5596 }
5597 
5598 /*
5599      This variable is used to prevent counting of MatAssemblyBegin() that
5600    are called from within a MatAssemblyEnd().
5601 */
5602 static PetscInt MatAssemblyEnd_InUse = 0;
5603 /*@
5604    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5605    be called after completing all calls to `MatSetValues()`.
5606 
5607    Collective
5608 
5609    Input Parameters:
5610 +  mat - the matrix
5611 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5612 
5613    Notes:
5614    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5615    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5616 
5617    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5618    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5619    using the matrix.
5620 
5621    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5622    same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is
5623    a global collective operation requiring all processes that share the matrix.
5624 
5625    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5626    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5627    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5628 
5629    Level: beginner
5630 
5631 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5632 @*/
5633 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5634 {
5635   PetscFunctionBegin;
5636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5637   PetscValidType(mat, 1);
5638   MatCheckPreallocated(mat, 1);
5639   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5640   if (mat->assembled) {
5641     mat->was_assembled = PETSC_TRUE;
5642     mat->assembled     = PETSC_FALSE;
5643   }
5644 
5645   if (!MatAssemblyEnd_InUse) {
5646     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5647     PetscTryTypeMethod(mat, assemblybegin, type);
5648     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5649   } else PetscTryTypeMethod(mat, assemblybegin, type);
5650   PetscFunctionReturn(0);
5651 }
5652 
5653 /*@
5654    MatAssembled - Indicates if a matrix has been assembled and is ready for
5655      use; for example, in matrix-vector product.
5656 
5657    Not Collective
5658 
5659    Input Parameter:
5660 .  mat - the matrix
5661 
5662    Output Parameter:
5663 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5664 
5665    Level: advanced
5666 
5667 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5668 @*/
5669 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5670 {
5671   PetscFunctionBegin;
5672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5673   PetscValidBoolPointer(assembled, 2);
5674   *assembled = mat->assembled;
5675   PetscFunctionReturn(0);
5676 }
5677 
5678 /*@
5679    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5680    be called after `MatAssemblyBegin()`.
5681 
5682    Collective on Mat
5683 
5684    Input Parameters:
5685 +  mat - the matrix
5686 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5687 
5688    Options Database Keys:
5689 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5690 .  -mat_view ::ascii_info_detail - Prints more detailed info
5691 .  -mat_view - Prints matrix in ASCII format
5692 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5693 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5694 .  -display <name> - Sets display name (default is host)
5695 .  -draw_pause <sec> - Sets number of seconds to pause after display
5696 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5697 .  -viewer_socket_machine <machine> - Machine to use for socket
5698 .  -viewer_socket_port <port> - Port number to use for socket
5699 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5700 
5701    Level: beginner
5702 
5703 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5704 @*/
5705 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5706 {
5707   static PetscInt inassm = 0;
5708   PetscBool       flg    = PETSC_FALSE;
5709 
5710   PetscFunctionBegin;
5711   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5712   PetscValidType(mat, 1);
5713 
5714   inassm++;
5715   MatAssemblyEnd_InUse++;
5716   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5717     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5718     PetscTryTypeMethod(mat, assemblyend, type);
5719     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5720   } else PetscTryTypeMethod(mat, assemblyend, type);
5721 
5722   /* Flush assembly is not a true assembly */
5723   if (type != MAT_FLUSH_ASSEMBLY) {
5724     if (mat->num_ass) {
5725       if (!mat->symmetry_eternal) {
5726         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5727         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5728       }
5729       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5730       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5731     }
5732     mat->num_ass++;
5733     mat->assembled        = PETSC_TRUE;
5734     mat->ass_nonzerostate = mat->nonzerostate;
5735   }
5736 
5737   mat->insertmode = NOT_SET_VALUES;
5738   MatAssemblyEnd_InUse--;
5739   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5740   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5741     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5742 
5743     if (mat->checksymmetryonassembly) {
5744       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5745       if (flg) {
5746         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5747       } else {
5748         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5749       }
5750     }
5751     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5752   }
5753   inassm--;
5754   PetscFunctionReturn(0);
5755 }
5756 
5757 /*@
5758    MatSetOption - Sets a parameter option for a matrix. Some options
5759    may be specific to certain storage formats.  Some options
5760    determine how values will be inserted (or added). Sorted,
5761    row-oriented input will generally assemble the fastest. The default
5762    is row-oriented.
5763 
5764    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5765 
5766    Input Parameters:
5767 +  mat - the matrix
5768 .  option - the option, one of those listed below (and possibly others),
5769 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5770 
5771   Options Describing Matrix Structure:
5772 +    `MAT_SPD` - symmetric positive definite
5773 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5774 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5775 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5776 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5777 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5778 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5779 
5780    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5781    do not need to be computed (usually at a high cost)
5782 
5783    Options For Use with `MatSetValues()`:
5784    Insert a logically dense subblock, which can be
5785 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5786 
5787    Note these options reflect the data you pass in with `MatSetValues()`; it has
5788    nothing to do with how the data is stored internally in the matrix
5789    data structure.
5790 
5791    When (re)assembling a matrix, we can restrict the input for
5792    efficiency/debugging purposes.  These options include
5793 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5794 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5795 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5796 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5797 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5798 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5799         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5800         performance for very large process counts.
5801 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5802         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5803         functions, instead sending only neighbor messages.
5804 
5805    Notes:
5806    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5807 
5808    Some options are relevant only for particular matrix types and
5809    are thus ignored by others.  Other options are not supported by
5810    certain matrix types and will generate an error message if set.
5811 
5812    If using Fortran to compute a matrix, one may need to
5813    use the column-oriented option (or convert to the row-oriented
5814    format).
5815 
5816    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5817    that would generate a new entry in the nonzero structure is instead
5818    ignored.  Thus, if memory has not alredy been allocated for this particular
5819    data, then the insertion is ignored. For dense matrices, in which
5820    the entire array is allocated, no entries are ever ignored.
5821    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5822 
5823    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5824    that would generate a new entry in the nonzero structure instead produces
5825    an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5826 
5827    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5828    that would generate a new entry that has not been preallocated will
5829    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5830    only.) This is a useful flag when debugging matrix memory preallocation.
5831    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5832 
5833    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5834    other processors should be dropped, rather than stashed.
5835    This is useful if you know that the "owning" processor is also
5836    always generating the correct matrix entries, so that PETSc need
5837    not transfer duplicate entries generated on another processor.
5838 
5839    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5840    searches during matrix assembly. When this flag is set, the hash table
5841    is created during the first matrix assembly. This hash table is
5842    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5843    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5844    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5845    supported by` MATMPIBAIJ` format only.
5846 
5847    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5848    are kept in the nonzero structure
5849 
5850    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5851    a zero location in the matrix
5852 
5853    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5854 
5855    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5856         zero row routines and thus improves performance for very large process counts.
5857 
5858    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5859         part of the matrix (since they should match the upper triangular part).
5860 
5861    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5862                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5863                      with finite difference schemes with non-periodic boundary conditions.
5864 
5865    Developer Note:
5866    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5867    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5868    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5869    not changed.
5870 
5871    Level: intermediate
5872 
5873 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5874 @*/
5875 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5876 {
5877   PetscFunctionBegin;
5878   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5879   if (op > 0) {
5880     PetscValidLogicalCollectiveEnum(mat, op, 2);
5881     PetscValidLogicalCollectiveBool(mat, flg, 3);
5882   }
5883 
5884   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5885 
5886   switch (op) {
5887   case MAT_FORCE_DIAGONAL_ENTRIES:
5888     mat->force_diagonals = flg;
5889     PetscFunctionReturn(0);
5890   case MAT_NO_OFF_PROC_ENTRIES:
5891     mat->nooffprocentries = flg;
5892     PetscFunctionReturn(0);
5893   case MAT_SUBSET_OFF_PROC_ENTRIES:
5894     mat->assembly_subset = flg;
5895     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5896 #if !defined(PETSC_HAVE_MPIUNI)
5897       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5898 #endif
5899       mat->stash.first_assembly_done = PETSC_FALSE;
5900     }
5901     PetscFunctionReturn(0);
5902   case MAT_NO_OFF_PROC_ZERO_ROWS:
5903     mat->nooffproczerorows = flg;
5904     PetscFunctionReturn(0);
5905   case MAT_SPD:
5906     if (flg) {
5907       mat->spd                    = PETSC_BOOL3_TRUE;
5908       mat->symmetric              = PETSC_BOOL3_TRUE;
5909       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5910     } else {
5911       mat->spd = PETSC_BOOL3_FALSE;
5912     }
5913     break;
5914   case MAT_SYMMETRIC:
5915     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5916     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5917 #if !defined(PETSC_USE_COMPLEX)
5918     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5919 #endif
5920     break;
5921   case MAT_HERMITIAN:
5922     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5923     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5924 #if !defined(PETSC_USE_COMPLEX)
5925     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5926 #endif
5927     break;
5928   case MAT_STRUCTURALLY_SYMMETRIC:
5929     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5930     break;
5931   case MAT_SYMMETRY_ETERNAL:
5932     PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false");
5933     mat->symmetry_eternal = flg;
5934     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5935     break;
5936   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5937     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false");
5938     mat->structural_symmetry_eternal = flg;
5939     break;
5940   case MAT_SPD_ETERNAL:
5941     PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false");
5942     mat->spd_eternal = flg;
5943     if (flg) {
5944       mat->structural_symmetry_eternal = PETSC_TRUE;
5945       mat->symmetry_eternal            = PETSC_TRUE;
5946     }
5947     break;
5948   case MAT_STRUCTURE_ONLY:
5949     mat->structure_only = flg;
5950     break;
5951   case MAT_SORTED_FULL:
5952     mat->sortedfull = flg;
5953     break;
5954   default:
5955     break;
5956   }
5957   PetscTryTypeMethod(mat, setoption, op, flg);
5958   PetscFunctionReturn(0);
5959 }
5960 
5961 /*@
5962    MatGetOption - Gets a parameter option that has been set for a matrix.
5963 
5964    Logically Collective
5965 
5966    Input Parameters:
5967 +  mat - the matrix
5968 -  option - the option, this only responds to certain options, check the code for which ones
5969 
5970    Output Parameter:
5971 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5972 
5973     Notes:
5974     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5975 
5976     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5977     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5978 
5979    Level: intermediate
5980 
5981 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5982     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5983 @*/
5984 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5985 {
5986   PetscFunctionBegin;
5987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5988   PetscValidType(mat, 1);
5989 
5990   PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op);
5991   PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()");
5992 
5993   switch (op) {
5994   case MAT_NO_OFF_PROC_ENTRIES:
5995     *flg = mat->nooffprocentries;
5996     break;
5997   case MAT_NO_OFF_PROC_ZERO_ROWS:
5998     *flg = mat->nooffproczerorows;
5999     break;
6000   case MAT_SYMMETRIC:
6001     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6002     break;
6003   case MAT_HERMITIAN:
6004     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6005     break;
6006   case MAT_STRUCTURALLY_SYMMETRIC:
6007     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6008     break;
6009   case MAT_SPD:
6010     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6011     break;
6012   case MAT_SYMMETRY_ETERNAL:
6013     *flg = mat->symmetry_eternal;
6014     break;
6015   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6016     *flg = mat->symmetry_eternal;
6017     break;
6018   default:
6019     break;
6020   }
6021   PetscFunctionReturn(0);
6022 }
6023 
6024 /*@
6025    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6026    this routine retains the old nonzero structure.
6027 
6028    Logically Collective
6029 
6030    Input Parameters:
6031 .  mat - the matrix
6032 
6033    Level: intermediate
6034 
6035    Note:
6036     If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase.
6037    See the Performance chapter of the users manual for information on preallocating matrices.
6038 
6039 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6040 @*/
6041 PetscErrorCode MatZeroEntries(Mat mat)
6042 {
6043   PetscFunctionBegin;
6044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6045   PetscValidType(mat, 1);
6046   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6047   PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled");
6048   MatCheckPreallocated(mat, 1);
6049 
6050   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6051   PetscUseTypeMethod(mat, zeroentries);
6052   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6053   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6054   PetscFunctionReturn(0);
6055 }
6056 
6057 /*@
6058    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6059    of a set of rows and columns of a matrix.
6060 
6061    Collective
6062 
6063    Input Parameters:
6064 +  mat - the matrix
6065 .  numRows - the number of rows to remove
6066 .  rows - the global row indices
6067 .  diag - value put in the diagonal of the eliminated rows
6068 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6069 -  b - optional vector of right hand side, that will be adjusted by provided solution
6070 
6071    Notes:
6072    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6073 
6074    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6075    The other entries of b will be adjusted by the known values of x times the corresponding matrix entries in the columns that are being eliminated
6076 
6077    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6078    Krylov method to take advantage of the known solution on the zeroed rows.
6079 
6080    For the parallel case, all processes that share the matrix (i.e.,
6081    those in the communicator used for matrix creation) MUST call this
6082    routine, regardless of whether any rows being zeroed are owned by
6083    them.
6084 
6085    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6086 
6087    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6088    list only rows local to itself).
6089 
6090    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6091 
6092    Level: intermediate
6093 
6094 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6095           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6096 @*/
6097 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6098 {
6099   PetscFunctionBegin;
6100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6101   PetscValidType(mat, 1);
6102   if (numRows) PetscValidIntPointer(rows, 3);
6103   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6104   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6105   MatCheckPreallocated(mat, 1);
6106 
6107   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6108   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6109   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6110   PetscFunctionReturn(0);
6111 }
6112 
6113 /*@
6114    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6115    of a set of rows and columns of a matrix.
6116 
6117    Collective
6118 
6119    Input Parameters:
6120 +  mat - the matrix
6121 .  is - the rows to zero
6122 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6123 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6124 -  b - optional vector of right hand side, that will be adjusted by provided solution
6125 
6126    Note:
6127    See `MatZeroRowsColumns()` for details on how this routine operates.
6128 
6129    Level: intermediate
6130 
6131 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6132           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6133 @*/
6134 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6135 {
6136   PetscInt        numRows;
6137   const PetscInt *rows;
6138 
6139   PetscFunctionBegin;
6140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6141   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6142   PetscValidType(mat, 1);
6143   PetscValidType(is, 2);
6144   PetscCall(ISGetLocalSize(is, &numRows));
6145   PetscCall(ISGetIndices(is, &rows));
6146   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6147   PetscCall(ISRestoreIndices(is, &rows));
6148   PetscFunctionReturn(0);
6149 }
6150 
6151 /*@
6152    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6153    of a set of rows of a matrix.
6154 
6155    Collective
6156 
6157    Input Parameters:
6158 +  mat - the matrix
6159 .  numRows - the number of rows to remove
6160 .  rows - the global row indices
6161 .  diag - value put in the diagonal of the eliminated rows
6162 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6163 -  b - optional vector of right hand side, that will be adjusted by provided solution
6164 
6165    Notes:
6166    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6167 
6168    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6169 
6170    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6171    Krylov method to take advantage of the known solution on the zeroed rows.
6172 
6173    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6174    from the matrix.
6175 
6176    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6177    but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6178    formats this does not alter the nonzero structure.
6179 
6180    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6181    of the matrix is not changed the values are
6182    merely zeroed.
6183 
6184    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6185    formats can optionally remove the main diagonal entry from the
6186    nonzero structure as well, by passing 0.0 as the final argument).
6187 
6188    For the parallel case, all processes that share the matrix (i.e.,
6189    those in the communicator used for matrix creation) MUST call this
6190    routine, regardless of whether any rows being zeroed are owned by
6191    them.
6192 
6193    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6194    list only rows local to itself).
6195 
6196    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6197    owns that are to be zeroed. This saves a global synchronization in the implementation.
6198 
6199    Level: intermediate
6200 
6201 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6202           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6203 @*/
6204 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6205 {
6206   PetscFunctionBegin;
6207   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6208   PetscValidType(mat, 1);
6209   if (numRows) PetscValidIntPointer(rows, 3);
6210   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6211   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6212   MatCheckPreallocated(mat, 1);
6213 
6214   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6215   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6216   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6217   PetscFunctionReturn(0);
6218 }
6219 
6220 /*@
6221    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6222    of a set of rows of a matrix.
6223 
6224    Collective on Mat
6225 
6226    Input Parameters:
6227 +  mat - the matrix
6228 .  is - index set of rows to remove (if NULL then no row is removed)
6229 .  diag - value put in all diagonals of eliminated rows
6230 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6231 -  b - optional vector of right hand side, that will be adjusted by provided solution
6232 
6233    Note:
6234    See `MatZeroRows()` for details on how this routine operates.
6235 
6236    Level: intermediate
6237 
6238 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6239           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6240 @*/
6241 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6242 {
6243   PetscInt        numRows = 0;
6244   const PetscInt *rows    = NULL;
6245 
6246   PetscFunctionBegin;
6247   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6248   PetscValidType(mat, 1);
6249   if (is) {
6250     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6251     PetscCall(ISGetLocalSize(is, &numRows));
6252     PetscCall(ISGetIndices(is, &rows));
6253   }
6254   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6255   if (is) PetscCall(ISRestoreIndices(is, &rows));
6256   PetscFunctionReturn(0);
6257 }
6258 
6259 /*@
6260    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6261    of a set of rows of a matrix. These rows must be local to the process.
6262 
6263    Collective
6264 
6265    Input Parameters:
6266 +  mat - the matrix
6267 .  numRows - the number of rows to remove
6268 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6269 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6270 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6271 -  b - optional vector of right hand side, that will be adjusted by provided solution
6272 
6273    Level: intermediate
6274 
6275    Notes:
6276    See `MatZeroRows()` for details on how this routine operates.
6277 
6278    The grid coordinates are across the entire grid, not just the local portion
6279 
6280    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6281    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6282    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6283    `DM_BOUNDARY_PERIODIC` boundary type.
6284 
6285    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6286    a single value per point) you can skip filling those indices.
6287 
6288    Fortran Note:
6289    idxm and idxn should be declared as
6290 $     MatStencil idxm(4,m)
6291    and the values inserted using
6292 .vb
6293     idxm(MatStencil_i,1) = i
6294     idxm(MatStencil_j,1) = j
6295     idxm(MatStencil_k,1) = k
6296     idxm(MatStencil_c,1) = c
6297    etc
6298 .ve
6299 
6300 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6301           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6302 @*/
6303 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6304 {
6305   PetscInt  dim    = mat->stencil.dim;
6306   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6307   PetscInt *dims   = mat->stencil.dims + 1;
6308   PetscInt *starts = mat->stencil.starts;
6309   PetscInt *dxm    = (PetscInt *)rows;
6310   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6311 
6312   PetscFunctionBegin;
6313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6314   PetscValidType(mat, 1);
6315   if (numRows) PetscValidPointer(rows, 3);
6316 
6317   PetscCall(PetscMalloc1(numRows, &jdxm));
6318   for (i = 0; i < numRows; ++i) {
6319     /* Skip unused dimensions (they are ordered k, j, i, c) */
6320     for (j = 0; j < 3 - sdim; ++j) dxm++;
6321     /* Local index in X dir */
6322     tmp = *dxm++ - starts[0];
6323     /* Loop over remaining dimensions */
6324     for (j = 0; j < dim - 1; ++j) {
6325       /* If nonlocal, set index to be negative */
6326       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6327       /* Update local index */
6328       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6329     }
6330     /* Skip component slot if necessary */
6331     if (mat->stencil.noc) dxm++;
6332     /* Local row number */
6333     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6334   }
6335   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6336   PetscCall(PetscFree(jdxm));
6337   PetscFunctionReturn(0);
6338 }
6339 
6340 /*@
6341    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6342    of a set of rows and columns of a matrix.
6343 
6344    Collective
6345 
6346    Input Parameters:
6347 +  mat - the matrix
6348 .  numRows - the number of rows/columns to remove
6349 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6350 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6351 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6352 -  b - optional vector of right hand side, that will be adjusted by provided solution
6353 
6354    Level: intermediate
6355 
6356    Notes:
6357    See `MatZeroRowsColumns()` for details on how this routine operates.
6358 
6359    The grid coordinates are across the entire grid, not just the local portion
6360 
6361    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6362    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6363    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6364    `DM_BOUNDARY_PERIODIC` boundary type.
6365 
6366    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
6367    a single value per point) you can skip filling those indices.
6368 
6369    Fortran Note:
6370    In Fortran idxm and idxn should be declared as
6371 $     MatStencil idxm(4,m)
6372    and the values inserted using
6373 .vb
6374     idxm(MatStencil_i,1) = i
6375     idxm(MatStencil_j,1) = j
6376     idxm(MatStencil_k,1) = k
6377     idxm(MatStencil_c,1) = c
6378     etc
6379 .ve
6380 
6381 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6382           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6383 @*/
6384 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6385 {
6386   PetscInt  dim    = mat->stencil.dim;
6387   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6388   PetscInt *dims   = mat->stencil.dims + 1;
6389   PetscInt *starts = mat->stencil.starts;
6390   PetscInt *dxm    = (PetscInt *)rows;
6391   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6392 
6393   PetscFunctionBegin;
6394   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6395   PetscValidType(mat, 1);
6396   if (numRows) PetscValidPointer(rows, 3);
6397 
6398   PetscCall(PetscMalloc1(numRows, &jdxm));
6399   for (i = 0; i < numRows; ++i) {
6400     /* Skip unused dimensions (they are ordered k, j, i, c) */
6401     for (j = 0; j < 3 - sdim; ++j) dxm++;
6402     /* Local index in X dir */
6403     tmp = *dxm++ - starts[0];
6404     /* Loop over remaining dimensions */
6405     for (j = 0; j < dim - 1; ++j) {
6406       /* If nonlocal, set index to be negative */
6407       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6408       /* Update local index */
6409       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6410     }
6411     /* Skip component slot if necessary */
6412     if (mat->stencil.noc) dxm++;
6413     /* Local row number */
6414     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6415   }
6416   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6417   PetscCall(PetscFree(jdxm));
6418   PetscFunctionReturn(0);
6419 }
6420 
6421 /*@C
6422    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6423    of a set of rows of a matrix; using local numbering of rows.
6424 
6425    Collective
6426 
6427    Input Parameters:
6428 +  mat - the matrix
6429 .  numRows - the number of rows to remove
6430 .  rows - the local row indices
6431 .  diag - value put in all diagonals of eliminated rows
6432 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6433 -  b - optional vector of right hand side, that will be adjusted by provided solution
6434 
6435    Notes:
6436    Before calling `MatZeroRowsLocal()`, the user must first set the
6437    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6438 
6439    See `MatZeroRows()` for details on how this routine operates.
6440 
6441    Level: intermediate
6442 
6443 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6444           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6445 @*/
6446 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6447 {
6448   PetscFunctionBegin;
6449   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6450   PetscValidType(mat, 1);
6451   if (numRows) PetscValidIntPointer(rows, 3);
6452   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6453   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6454   MatCheckPreallocated(mat, 1);
6455 
6456   if (mat->ops->zerorowslocal) {
6457     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6458   } else {
6459     IS              is, newis;
6460     const PetscInt *newRows;
6461 
6462     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6463     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6464     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6465     PetscCall(ISGetIndices(newis, &newRows));
6466     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6467     PetscCall(ISRestoreIndices(newis, &newRows));
6468     PetscCall(ISDestroy(&newis));
6469     PetscCall(ISDestroy(&is));
6470   }
6471   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6472   PetscFunctionReturn(0);
6473 }
6474 
6475 /*@
6476    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6477    of a set of rows of a matrix; using local numbering of rows.
6478 
6479    Collective
6480 
6481    Input Parameters:
6482 +  mat - the matrix
6483 .  is - index set of rows to remove
6484 .  diag - value put in all diagonals of eliminated rows
6485 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6486 -  b - optional vector of right hand side, that will be adjusted by provided solution
6487 
6488    Notes:
6489    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6490    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6491 
6492    See `MatZeroRows()` for details on how this routine operates.
6493 
6494    Level: intermediate
6495 
6496 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6497           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6498 @*/
6499 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6500 {
6501   PetscInt        numRows;
6502   const PetscInt *rows;
6503 
6504   PetscFunctionBegin;
6505   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6506   PetscValidType(mat, 1);
6507   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6508   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6509   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6510   MatCheckPreallocated(mat, 1);
6511 
6512   PetscCall(ISGetLocalSize(is, &numRows));
6513   PetscCall(ISGetIndices(is, &rows));
6514   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6515   PetscCall(ISRestoreIndices(is, &rows));
6516   PetscFunctionReturn(0);
6517 }
6518 
6519 /*@
6520    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6521    of a set of rows and columns of a matrix; using local numbering of rows.
6522 
6523    Collective
6524 
6525    Input Parameters:
6526 +  mat - the matrix
6527 .  numRows - the number of rows to remove
6528 .  rows - the global row indices
6529 .  diag - value put in all diagonals of eliminated rows
6530 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6531 -  b - optional vector of right hand side, that will be adjusted by provided solution
6532 
6533    Notes:
6534    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6535    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6536 
6537    See `MatZeroRowsColumns()` for details on how this routine operates.
6538 
6539    Level: intermediate
6540 
6541 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6542           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6543 @*/
6544 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6545 {
6546   IS              is, newis;
6547   const PetscInt *newRows;
6548 
6549   PetscFunctionBegin;
6550   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6551   PetscValidType(mat, 1);
6552   if (numRows) PetscValidIntPointer(rows, 3);
6553   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6554   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6555   MatCheckPreallocated(mat, 1);
6556 
6557   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6558   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6559   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6560   PetscCall(ISGetIndices(newis, &newRows));
6561   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6562   PetscCall(ISRestoreIndices(newis, &newRows));
6563   PetscCall(ISDestroy(&newis));
6564   PetscCall(ISDestroy(&is));
6565   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6566   PetscFunctionReturn(0);
6567 }
6568 
6569 /*@
6570    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6571    of a set of rows and columns of a matrix; using local numbering of rows.
6572 
6573    Collective on Mat
6574 
6575    Input Parameters:
6576 +  mat - the matrix
6577 .  is - index set of rows to remove
6578 .  diag - value put in all diagonals of eliminated rows
6579 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6580 -  b - optional vector of right hand side, that will be adjusted by provided solution
6581 
6582    Notes:
6583    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6584    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6585 
6586    See `MatZeroRowsColumns()` for details on how this routine operates.
6587 
6588    Level: intermediate
6589 
6590 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6591           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6592 @*/
6593 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6594 {
6595   PetscInt        numRows;
6596   const PetscInt *rows;
6597 
6598   PetscFunctionBegin;
6599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6600   PetscValidType(mat, 1);
6601   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6602   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6603   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6604   MatCheckPreallocated(mat, 1);
6605 
6606   PetscCall(ISGetLocalSize(is, &numRows));
6607   PetscCall(ISGetIndices(is, &rows));
6608   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6609   PetscCall(ISRestoreIndices(is, &rows));
6610   PetscFunctionReturn(0);
6611 }
6612 
6613 /*@C
6614    MatGetSize - Returns the numbers of rows and columns in a matrix.
6615 
6616    Not Collective
6617 
6618    Input Parameter:
6619 .  mat - the matrix
6620 
6621    Output Parameters:
6622 +  m - the number of global rows
6623 -  n - the number of global columns
6624 
6625    Note: both output parameters can be NULL on input.
6626 
6627    Level: beginner
6628 
6629 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6630 @*/
6631 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6632 {
6633   PetscFunctionBegin;
6634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6635   if (m) *m = mat->rmap->N;
6636   if (n) *n = mat->cmap->N;
6637   PetscFunctionReturn(0);
6638 }
6639 
6640 /*@C
6641    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6642    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6643 
6644    Not Collective
6645 
6646    Input Parameter:
6647 .  mat - the matrix
6648 
6649    Output Parameters:
6650 +  m - the number of local rows, use `NULL` to not obtain this value
6651 -  n - the number of local columns, use `NULL` to not obtain this value
6652 
6653    Level: beginner
6654 
6655 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6656 @*/
6657 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6658 {
6659   PetscFunctionBegin;
6660   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6661   if (m) PetscValidIntPointer(m, 2);
6662   if (n) PetscValidIntPointer(n, 3);
6663   if (m) *m = mat->rmap->n;
6664   if (n) *n = mat->cmap->n;
6665   PetscFunctionReturn(0);
6666 }
6667 
6668 /*@C
6669    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6670    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6671 
6672    Not Collective, unless matrix has not been allocated, then collective
6673 
6674    Input Parameter:
6675 .  mat - the matrix
6676 
6677    Output Parameters:
6678 +  m - the global index of the first local column, use `NULL` to not obtain this value
6679 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6680 
6681    Level: developer
6682 
6683 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6684 @*/
6685 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6686 {
6687   PetscFunctionBegin;
6688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6689   PetscValidType(mat, 1);
6690   if (m) PetscValidIntPointer(m, 2);
6691   if (n) PetscValidIntPointer(n, 3);
6692   MatCheckPreallocated(mat, 1);
6693   if (m) *m = mat->cmap->rstart;
6694   if (n) *n = mat->cmap->rend;
6695   PetscFunctionReturn(0);
6696 }
6697 
6698 /*@C
6699    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6700    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6701    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6702 
6703    Not Collective
6704 
6705    Input Parameter:
6706 .  mat - the matrix
6707 
6708    Output Parameters:
6709 +  m - the global index of the first local row, use `NULL` to not obtain this value
6710 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6711 
6712    Note:
6713   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6714   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6715   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6716 
6717    Level: beginner
6718 
6719 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6720           `PetscLayout`
6721 @*/
6722 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6723 {
6724   PetscFunctionBegin;
6725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6726   PetscValidType(mat, 1);
6727   if (m) PetscValidIntPointer(m, 2);
6728   if (n) PetscValidIntPointer(n, 3);
6729   MatCheckPreallocated(mat, 1);
6730   if (m) *m = mat->rmap->rstart;
6731   if (n) *n = mat->rmap->rend;
6732   PetscFunctionReturn(0);
6733 }
6734 
6735 /*@C
6736    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6737    each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6738    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6739 
6740    Not Collective, unless matrix has not been allocated, then collective
6741 
6742    Input Parameters:
6743 .  mat - the matrix
6744 
6745    Output Parameters:
6746 .  ranges - start of each processors portion plus one more than the total length at the end
6747 
6748    Level: beginner
6749 
6750 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6751 @*/
6752 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6753 {
6754   PetscFunctionBegin;
6755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6756   PetscValidType(mat, 1);
6757   MatCheckPreallocated(mat, 1);
6758   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6759   PetscFunctionReturn(0);
6760 }
6761 
6762 /*@C
6763    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6764    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6765 
6766    Not Collective, unless matrix has not been allocated, then collective on Mat
6767 
6768    Input Parameters:
6769 .  mat - the matrix
6770 
6771    Output Parameters:
6772 .  ranges - start of each processors portion plus one more then the total length at the end
6773 
6774    Level: beginner
6775 
6776 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6777 @*/
6778 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6779 {
6780   PetscFunctionBegin;
6781   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6782   PetscValidType(mat, 1);
6783   MatCheckPreallocated(mat, 1);
6784   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6785   PetscFunctionReturn(0);
6786 }
6787 
6788 /*@C
6789    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6790    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6791    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6792 
6793    Not Collective
6794 
6795    Input Parameter:
6796 .  A - matrix
6797 
6798    Output Parameters:
6799 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6800 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6801 
6802    Level: intermediate
6803 
6804 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6805 @*/
6806 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6807 {
6808   PetscErrorCode (*f)(Mat, IS *, IS *);
6809 
6810   PetscFunctionBegin;
6811   MatCheckPreallocated(A, 1);
6812   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6813   if (f) {
6814     PetscCall((*f)(A, rows, cols));
6815   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6816     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6817     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6818   }
6819   PetscFunctionReturn(0);
6820 }
6821 
6822 /*@C
6823    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6824    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6825    to complete the factorization.
6826 
6827    Collective on fact
6828 
6829    Input Parameters:
6830 +  fact - the factorized matrix obtained with `MatGetFactor()`
6831 .  mat - the matrix
6832 .  row - row permutation
6833 .  column - column permutation
6834 -  info - structure containing
6835 $      levels - number of levels of fill.
6836 $      expected fill - as ratio of original fill.
6837 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6838                 missing diagonal entries)
6839 
6840    Output Parameters:
6841 .  fact - new matrix that has been symbolically factored
6842 
6843    Level: developer
6844 
6845    Notes:
6846    See [Matrix Factorization](sec_matfactor) for additional information.
6847 
6848    Most users should employ the `KSP` interface for linear solvers
6849    instead of working directly with matrix algebra routines such as this.
6850    See, e.g., `KSPCreate()`.
6851 
6852    Uses the definition of level of fill as in Y. Saad, 2003
6853 
6854    Developer Note:
6855    The Fortran interface is not autogenerated as the
6856    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6857 
6858    References:
6859 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6860 
6861 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6862           `MatGetOrdering()`, `MatFactorInfo`
6863 @*/
6864 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6865 {
6866   PetscFunctionBegin;
6867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6868   PetscValidType(mat, 2);
6869   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6870   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6871   PetscValidPointer(info, 5);
6872   PetscValidPointer(fact, 1);
6873   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6874   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6875   if (!fact->ops->ilufactorsymbolic) {
6876     MatSolverType stype;
6877     PetscCall(MatFactorGetSolverType(fact, &stype));
6878     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6879   }
6880   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6881   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6882   MatCheckPreallocated(mat, 2);
6883 
6884   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6885   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6886   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6887   PetscFunctionReturn(0);
6888 }
6889 
6890 /*@C
6891    MatICCFactorSymbolic - Performs symbolic incomplete
6892    Cholesky factorization for a symmetric matrix.  Use
6893    `MatCholeskyFactorNumeric()` to complete the factorization.
6894 
6895    Collective on fact
6896 
6897    Input Parameters:
6898 +  fact - the factorized matrix obtained with `MatGetFactor()`
6899 .  mat - the matrix to be factored
6900 .  perm - row and column permutation
6901 -  info - structure containing
6902 $      levels - number of levels of fill.
6903 $      expected fill - as ratio of original fill.
6904 
6905    Output Parameter:
6906 .  fact - the factored matrix
6907 
6908    Level: developer
6909 
6910    Notes:
6911    Most users should employ the `KSP` interface for linear solvers
6912    instead of working directly with matrix algebra routines such as this.
6913    See, e.g., `KSPCreate()`.
6914 
6915    This uses the definition of level of fill as in Y. Saad, 2003
6916 
6917    Developer Note:
6918    The Fortran interface is not autogenerated as the
6919    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6920 
6921    References:
6922 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6923 
6924 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6925 @*/
6926 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6927 {
6928   PetscFunctionBegin;
6929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6930   PetscValidType(mat, 2);
6931   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6932   PetscValidPointer(info, 4);
6933   PetscValidPointer(fact, 1);
6934   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6935   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6936   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6937   if (!(fact)->ops->iccfactorsymbolic) {
6938     MatSolverType stype;
6939     PetscCall(MatFactorGetSolverType(fact, &stype));
6940     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6941   }
6942   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6943   MatCheckPreallocated(mat, 2);
6944 
6945   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6946   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6947   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6948   PetscFunctionReturn(0);
6949 }
6950 
6951 /*@C
6952    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6953    points to an array of valid matrices, they may be reused to store the new
6954    submatrices.
6955 
6956    Collective
6957 
6958    Input Parameters:
6959 +  mat - the matrix
6960 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6961 .  irow, icol - index sets of rows and columns to extract
6962 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6963 
6964    Output Parameter:
6965 .  submat - the array of submatrices
6966 
6967    Notes:
6968    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6969    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6970    to extract a parallel submatrix.
6971 
6972    Some matrix types place restrictions on the row and column
6973    indices, such as that they be sorted or that they be equal to each other.
6974 
6975    The index sets may not have duplicate entries.
6976 
6977    When extracting submatrices from a parallel matrix, each processor can
6978    form a different submatrix by setting the rows and columns of its
6979    individual index sets according to the local submatrix desired.
6980 
6981    When finished using the submatrices, the user should destroy
6982    them with `MatDestroySubMatrices()`.
6983 
6984    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6985    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6986 
6987    This routine creates the matrices in submat; you should NOT create them before
6988    calling it. It also allocates the array of matrix pointers submat.
6989 
6990    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6991    request one row/column in a block, they must request all rows/columns that are in
6992    that block. For example, if the block size is 2 you cannot request just row 0 and
6993    column 0.
6994 
6995    Fortran Note:
6996    The Fortran interface is slightly different from that given below; it
6997    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
6998 
6999    Level: advanced
7000 
7001 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7002 @*/
7003 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7004 {
7005   PetscInt  i;
7006   PetscBool eq;
7007 
7008   PetscFunctionBegin;
7009   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7010   PetscValidType(mat, 1);
7011   if (n) {
7012     PetscValidPointer(irow, 3);
7013     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7014     PetscValidPointer(icol, 4);
7015     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7016   }
7017   PetscValidPointer(submat, 6);
7018   if (n && scall == MAT_REUSE_MATRIX) {
7019     PetscValidPointer(*submat, 6);
7020     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7021   }
7022   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7023   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7024   MatCheckPreallocated(mat, 1);
7025   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7026   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7027   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7028   for (i = 0; i < n; i++) {
7029     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7030     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7031     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7032 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7033     if (mat->boundtocpu && mat->bindingpropagates) {
7034       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7035       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7036     }
7037 #endif
7038   }
7039   PetscFunctionReturn(0);
7040 }
7041 
7042 /*@C
7043    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7044 
7045    Collective
7046 
7047    Input Parameters:
7048 +  mat - the matrix
7049 .  n   - the number of submatrixes to be extracted
7050 .  irow, icol - index sets of rows and columns to extract
7051 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7052 
7053    Output Parameter:
7054 .  submat - the array of submatrices
7055 
7056    Level: advanced
7057 
7058    Note:
7059    This is used by `PCGASM`
7060 
7061 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7062 @*/
7063 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7064 {
7065   PetscInt  i;
7066   PetscBool eq;
7067 
7068   PetscFunctionBegin;
7069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7070   PetscValidType(mat, 1);
7071   if (n) {
7072     PetscValidPointer(irow, 3);
7073     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7074     PetscValidPointer(icol, 4);
7075     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7076   }
7077   PetscValidPointer(submat, 6);
7078   if (n && scall == MAT_REUSE_MATRIX) {
7079     PetscValidPointer(*submat, 6);
7080     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7081   }
7082   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7083   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7084   MatCheckPreallocated(mat, 1);
7085 
7086   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7087   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7088   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7089   for (i = 0; i < n; i++) {
7090     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7091     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7092   }
7093   PetscFunctionReturn(0);
7094 }
7095 
7096 /*@C
7097    MatDestroyMatrices - Destroys an array of matrices.
7098 
7099    Collective
7100 
7101    Input Parameters:
7102 +  n - the number of local matrices
7103 -  mat - the matrices (note that this is a pointer to the array of matrices)
7104 
7105    Level: advanced
7106 
7107     Note:
7108     Frees not only the matrices, but also the array that contains the matrices
7109            In Fortran will not free the array.
7110 
7111 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7112 @*/
7113 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7114 {
7115   PetscInt i;
7116 
7117   PetscFunctionBegin;
7118   if (!*mat) PetscFunctionReturn(0);
7119   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7120   PetscValidPointer(mat, 2);
7121 
7122   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7123 
7124   /* memory is allocated even if n = 0 */
7125   PetscCall(PetscFree(*mat));
7126   PetscFunctionReturn(0);
7127 }
7128 
7129 /*@C
7130    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7131 
7132    Collective
7133 
7134    Input Parameters:
7135 +  n - the number of local matrices
7136 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7137                        sequence of MatCreateSubMatrices())
7138 
7139    Level: advanced
7140 
7141     Note:
7142     Frees not only the matrices, but also the array that contains the matrices
7143            In Fortran will not free the array.
7144 
7145 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7146 @*/
7147 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7148 {
7149   Mat mat0;
7150 
7151   PetscFunctionBegin;
7152   if (!*mat) PetscFunctionReturn(0);
7153   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7154   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7155   PetscValidPointer(mat, 2);
7156 
7157   mat0 = (*mat)[0];
7158   if (mat0 && mat0->ops->destroysubmatrices) {
7159     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7160   } else {
7161     PetscCall(MatDestroyMatrices(n, mat));
7162   }
7163   PetscFunctionReturn(0);
7164 }
7165 
7166 /*@C
7167    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7168 
7169    Collective
7170 
7171    Input Parameters:
7172 .  mat - the matrix
7173 
7174    Output Parameter:
7175 .  matstruct - the sequential matrix with the nonzero structure of mat
7176 
7177   Level: developer
7178 
7179 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7180 @*/
7181 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7182 {
7183   PetscFunctionBegin;
7184   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7185   PetscValidPointer(matstruct, 2);
7186 
7187   PetscValidType(mat, 1);
7188   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7189   MatCheckPreallocated(mat, 1);
7190 
7191   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7192   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7193   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7194   PetscFunctionReturn(0);
7195 }
7196 
7197 /*@C
7198    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7199 
7200    Collective
7201 
7202    Input Parameters:
7203 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7204                        sequence of `MatGetSequentialNonzeroStructure()`)
7205 
7206    Level: advanced
7207 
7208     Note:
7209     Frees not only the matrices, but also the array that contains the matrices
7210 
7211 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7212 @*/
7213 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7214 {
7215   PetscFunctionBegin;
7216   PetscValidPointer(mat, 1);
7217   PetscCall(MatDestroy(mat));
7218   PetscFunctionReturn(0);
7219 }
7220 
7221 /*@
7222    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7223    replaces the index sets by larger ones that represent submatrices with
7224    additional overlap.
7225 
7226    Collective
7227 
7228    Input Parameters:
7229 +  mat - the matrix
7230 .  n   - the number of index sets
7231 .  is  - the array of index sets (these index sets will changed during the call)
7232 -  ov  - the additional overlap requested
7233 
7234    Options Database Key:
7235 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7236 
7237    Level: developer
7238 
7239    Note:
7240    The computed overlap preserves the matrix block sizes when the blocks are square.
7241    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7242    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7243 
7244 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7245 @*/
7246 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7247 {
7248   PetscInt i, bs, cbs;
7249 
7250   PetscFunctionBegin;
7251   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7252   PetscValidType(mat, 1);
7253   PetscValidLogicalCollectiveInt(mat, n, 2);
7254   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7255   if (n) {
7256     PetscValidPointer(is, 3);
7257     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7258   }
7259   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7260   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7261   MatCheckPreallocated(mat, 1);
7262 
7263   if (!ov || !n) PetscFunctionReturn(0);
7264   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7265   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7266   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7267   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7268   if (bs == cbs) {
7269     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7270   }
7271   PetscFunctionReturn(0);
7272 }
7273 
7274 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7275 
7276 /*@
7277    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7278    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7279    additional overlap.
7280 
7281    Collective
7282 
7283    Input Parameters:
7284 +  mat - the matrix
7285 .  n   - the number of index sets
7286 .  is  - the array of index sets (these index sets will changed during the call)
7287 -  ov  - the additional overlap requested
7288 
7289 `   Options Database Key:
7290 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7291 
7292    Level: developer
7293 
7294 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7295 @*/
7296 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7297 {
7298   PetscInt i;
7299 
7300   PetscFunctionBegin;
7301   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7302   PetscValidType(mat, 1);
7303   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7304   if (n) {
7305     PetscValidPointer(is, 3);
7306     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7307   }
7308   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7309   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7310   MatCheckPreallocated(mat, 1);
7311   if (!ov) PetscFunctionReturn(0);
7312   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7313   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7314   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7315   PetscFunctionReturn(0);
7316 }
7317 
7318 /*@
7319    MatGetBlockSize - Returns the matrix block size.
7320 
7321    Not Collective
7322 
7323    Input Parameter:
7324 .  mat - the matrix
7325 
7326    Output Parameter:
7327 .  bs - block size
7328 
7329    Notes:
7330     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7331 
7332    If the block size has not been set yet this routine returns 1.
7333 
7334    Level: intermediate
7335 
7336 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7337 @*/
7338 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7339 {
7340   PetscFunctionBegin;
7341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7342   PetscValidIntPointer(bs, 2);
7343   *bs = PetscAbs(mat->rmap->bs);
7344   PetscFunctionReturn(0);
7345 }
7346 
7347 /*@
7348    MatGetBlockSizes - Returns the matrix block row and column sizes.
7349 
7350    Not Collective
7351 
7352    Input Parameter:
7353 .  mat - the matrix
7354 
7355    Output Parameters:
7356 +  rbs - row block size
7357 -  cbs - column block size
7358 
7359    Notes:
7360     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7361     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7362 
7363    If a block size has not been set yet this routine returns 1.
7364 
7365    Level: intermediate
7366 
7367 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7368 @*/
7369 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7370 {
7371   PetscFunctionBegin;
7372   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7373   if (rbs) PetscValidIntPointer(rbs, 2);
7374   if (cbs) PetscValidIntPointer(cbs, 3);
7375   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7376   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7377   PetscFunctionReturn(0);
7378 }
7379 
7380 /*@
7381    MatSetBlockSize - Sets the matrix block size.
7382 
7383    Logically Collective
7384 
7385    Input Parameters:
7386 +  mat - the matrix
7387 -  bs - block size
7388 
7389    Notes:
7390     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7391     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7392 
7393     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7394     is compatible with the matrix local sizes.
7395 
7396    Level: intermediate
7397 
7398 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7399 @*/
7400 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7401 {
7402   PetscFunctionBegin;
7403   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7404   PetscValidLogicalCollectiveInt(mat, bs, 2);
7405   PetscCall(MatSetBlockSizes(mat, bs, bs));
7406   PetscFunctionReturn(0);
7407 }
7408 
7409 typedef struct {
7410   PetscInt         n;
7411   IS              *is;
7412   Mat             *mat;
7413   PetscObjectState nonzerostate;
7414   Mat              C;
7415 } EnvelopeData;
7416 
7417 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7418 {
7419   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7420   PetscCall(PetscFree(edata->is));
7421   PetscCall(PetscFree(edata));
7422   return 0;
7423 }
7424 
7425 /*
7426    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7427          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7428 
7429    Collective
7430 
7431    Input Parameter:
7432 .  mat - the matrix
7433 
7434    Notes:
7435      There can be zeros within the blocks
7436 
7437      The blocks can overlap between processes, including laying on more than two processes
7438 
7439 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7440 */
7441 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7442 {
7443   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7444   PetscInt          *diag, *odiag, sc;
7445   VecScatter         scatter;
7446   PetscScalar       *seqv;
7447   const PetscScalar *parv;
7448   const PetscInt    *ia, *ja;
7449   PetscBool          set, flag, done;
7450   Mat                AA = mat, A;
7451   MPI_Comm           comm;
7452   PetscMPIInt        rank, size, tag;
7453   MPI_Status         status;
7454   PetscContainer     container;
7455   EnvelopeData      *edata;
7456   Vec                seq, par;
7457   IS                 isglobal;
7458 
7459   PetscFunctionBegin;
7460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7461   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7462   if (!set || !flag) {
7463     /* TOO: only needs nonzero structure of transpose */
7464     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7465     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7466   }
7467   PetscCall(MatAIJGetLocalMat(AA, &A));
7468   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7469   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7470 
7471   PetscCall(MatGetLocalSize(mat, &n, NULL));
7472   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7473   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7474   PetscCallMPI(MPI_Comm_size(comm, &size));
7475   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7476 
7477   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7478 
7479   if (rank > 0) {
7480     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7481     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7482   }
7483   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7484   for (i = 0; i < n; i++) {
7485     env = PetscMax(env, ja[ia[i + 1] - 1]);
7486     II  = rstart + i;
7487     if (env == II) {
7488       starts[lblocks]  = tbs;
7489       sizes[lblocks++] = 1 + II - tbs;
7490       tbs              = 1 + II;
7491     }
7492   }
7493   if (rank < size - 1) {
7494     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7495     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7496   }
7497 
7498   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7499   if (!set || !flag) PetscCall(MatDestroy(&AA));
7500   PetscCall(MatDestroy(&A));
7501 
7502   PetscCall(PetscNew(&edata));
7503   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7504   edata->n = lblocks;
7505   /* create IS needed for extracting blocks from the original matrix */
7506   PetscCall(PetscMalloc1(lblocks, &edata->is));
7507   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7508 
7509   /* Create the resulting inverse matrix structure with preallocation information */
7510   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7511   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7512   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7513   PetscCall(MatSetType(edata->C, MATAIJ));
7514 
7515   /* Communicate the start and end of each row, from each block to the correct rank */
7516   /* TODO: Use PetscSF instead of VecScatter */
7517   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7518   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7519   PetscCall(VecGetArrayWrite(seq, &seqv));
7520   for (PetscInt i = 0; i < lblocks; i++) {
7521     for (PetscInt j = 0; j < sizes[i]; j++) {
7522       seqv[cnt]     = starts[i];
7523       seqv[cnt + 1] = starts[i] + sizes[i];
7524       cnt += 2;
7525     }
7526   }
7527   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7528   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7529   sc -= cnt;
7530   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7531   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7532   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7533   PetscCall(ISDestroy(&isglobal));
7534   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7535   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7536   PetscCall(VecScatterDestroy(&scatter));
7537   PetscCall(VecDestroy(&seq));
7538   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7539   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7540   PetscCall(VecGetArrayRead(par, &parv));
7541   cnt = 0;
7542   PetscCall(MatGetSize(mat, NULL, &n));
7543   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7544     PetscInt start, end, d = 0, od = 0;
7545 
7546     start = (PetscInt)PetscRealPart(parv[cnt]);
7547     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7548     cnt += 2;
7549 
7550     if (start < cstart) {
7551       od += cstart - start + n - cend;
7552       d += cend - cstart;
7553     } else if (start < cend) {
7554       od += n - cend;
7555       d += cend - start;
7556     } else od += n - start;
7557     if (end <= cstart) {
7558       od -= cstart - end + n - cend;
7559       d -= cend - cstart;
7560     } else if (end < cend) {
7561       od -= n - cend;
7562       d -= cend - end;
7563     } else od -= n - end;
7564 
7565     odiag[i] = od;
7566     diag[i]  = d;
7567   }
7568   PetscCall(VecRestoreArrayRead(par, &parv));
7569   PetscCall(VecDestroy(&par));
7570   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7571   PetscCall(PetscFree2(diag, odiag));
7572   PetscCall(PetscFree2(sizes, starts));
7573 
7574   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7575   PetscCall(PetscContainerSetPointer(container, edata));
7576   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7577   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7578   PetscCall(PetscObjectDereference((PetscObject)container));
7579   PetscFunctionReturn(0);
7580 }
7581 
7582 /*@
7583   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7584 
7585   Collective on A
7586 
7587   Input Parameters:
7588 . A - the matrix
7589 
7590   Output Parameters:
7591 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7592 
7593   Note:
7594      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7595 
7596   Level: advanced
7597 
7598 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7599 @*/
7600 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7601 {
7602   PetscContainer   container;
7603   EnvelopeData    *edata;
7604   PetscObjectState nonzerostate;
7605 
7606   PetscFunctionBegin;
7607   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7608   if (!container) {
7609     PetscCall(MatComputeVariableBlockEnvelope(A));
7610     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7611   }
7612   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7613   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7614   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7615   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7616 
7617   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7618   *C = edata->C;
7619 
7620   for (PetscInt i = 0; i < edata->n; i++) {
7621     Mat          D;
7622     PetscScalar *dvalues;
7623 
7624     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7625     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7626     PetscCall(MatSeqDenseInvert(D));
7627     PetscCall(MatDenseGetArray(D, &dvalues));
7628     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7629     PetscCall(MatDestroy(&D));
7630   }
7631   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7632   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7633   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7634   PetscFunctionReturn(0);
7635 }
7636 
7637 /*@
7638    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7639 
7640    Logically Collective
7641 
7642    Input Parameters:
7643 +  mat - the matrix
7644 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7645 -  bsizes - the block sizes
7646 
7647    Notes:
7648     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7649 
7650     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.
7651 
7652    Level: intermediate
7653 
7654 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7655           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7656 @*/
7657 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7658 {
7659   PetscInt i, ncnt = 0, nlocal;
7660 
7661   PetscFunctionBegin;
7662   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7663   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7664   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7665   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7666   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);
7667   PetscCall(PetscFree(mat->bsizes));
7668   mat->nblocks = nblocks;
7669   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7670   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7671   PetscFunctionReturn(0);
7672 }
7673 
7674 /*@C
7675    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7676 
7677    Logically Collective; No Fortran Support
7678 
7679    Input Parameter:
7680 .  mat - the matrix
7681 
7682    Output Parameters:
7683 +  nblocks - the number of blocks on this process
7684 -  bsizes - the block sizes
7685 
7686    Level: intermediate
7687 
7688 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7689 @*/
7690 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7691 {
7692   PetscFunctionBegin;
7693   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7694   *nblocks = mat->nblocks;
7695   *bsizes  = mat->bsizes;
7696   PetscFunctionReturn(0);
7697 }
7698 
7699 /*@
7700    MatSetBlockSizes - Sets the matrix block row and column sizes.
7701 
7702    Logically Collective
7703 
7704    Input Parameters:
7705 +  mat - the matrix
7706 .  rbs - row block size
7707 -  cbs - column block size
7708 
7709    Notes:
7710     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7711     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7712     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7713 
7714     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7715     are compatible with the matrix local sizes.
7716 
7717     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7718 
7719    Level: intermediate
7720 
7721 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7722 @*/
7723 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7724 {
7725   PetscFunctionBegin;
7726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7727   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7728   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7729   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7730   if (mat->rmap->refcnt) {
7731     ISLocalToGlobalMapping l2g  = NULL;
7732     PetscLayout            nmap = NULL;
7733 
7734     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7735     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7736     PetscCall(PetscLayoutDestroy(&mat->rmap));
7737     mat->rmap          = nmap;
7738     mat->rmap->mapping = l2g;
7739   }
7740   if (mat->cmap->refcnt) {
7741     ISLocalToGlobalMapping l2g  = NULL;
7742     PetscLayout            nmap = NULL;
7743 
7744     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7745     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7746     PetscCall(PetscLayoutDestroy(&mat->cmap));
7747     mat->cmap          = nmap;
7748     mat->cmap->mapping = l2g;
7749   }
7750   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7751   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7752   PetscFunctionReturn(0);
7753 }
7754 
7755 /*@
7756    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7757 
7758    Logically Collective
7759 
7760    Input Parameters:
7761 +  mat - the matrix
7762 .  fromRow - matrix from which to copy row block size
7763 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7764 
7765    Level: developer
7766 
7767 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7768 @*/
7769 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7770 {
7771   PetscFunctionBegin;
7772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7773   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7774   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7775   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7776   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7777   PetscFunctionReturn(0);
7778 }
7779 
7780 /*@
7781    MatResidual - Default routine to calculate the residual r = b - Ax
7782 
7783    Collective
7784 
7785    Input Parameters:
7786 +  mat - the matrix
7787 .  b   - the right-hand-side
7788 -  x   - the approximate solution
7789 
7790    Output Parameter:
7791 .  r - location to store the residual
7792 
7793    Level: developer
7794 
7795 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7796 @*/
7797 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7798 {
7799   PetscFunctionBegin;
7800   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7801   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7802   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7803   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7804   PetscValidType(mat, 1);
7805   MatCheckPreallocated(mat, 1);
7806   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7807   if (!mat->ops->residual) {
7808     PetscCall(MatMult(mat, x, r));
7809     PetscCall(VecAYPX(r, -1.0, b));
7810   } else {
7811     PetscUseTypeMethod(mat, residual, b, x, r);
7812   }
7813   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7814   PetscFunctionReturn(0);
7815 }
7816 
7817 /*@C
7818     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7819 
7820    Collective
7821 
7822     Input Parameters:
7823 +   mat - the matrix
7824 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7825 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7826 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7827                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7828                  always used.
7829 
7830     Output Parameters:
7831 +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7832 .   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
7833 .   ja - the column indices, use NULL if not needed
7834 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7835            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7836 
7837     Level: developer
7838 
7839     Notes:
7840     You CANNOT change any of the ia[] or ja[] values.
7841 
7842     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7843 
7844     Fortran Notes:
7845     In Fortran use
7846 .vb
7847       PetscInt ia(1), ja(1)
7848       PetscOffset iia, jja
7849       call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7850       ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7851 .ve
7852      or
7853 .vb
7854     PetscInt, pointer :: ia(:),ja(:)
7855     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7856     ! Access the ith and jth entries via ia(i) and ja(j)
7857 .ve
7858 
7859 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7860 @*/
7861 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7862 {
7863   PetscFunctionBegin;
7864   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7865   PetscValidType(mat, 1);
7866   if (n) PetscValidIntPointer(n, 5);
7867   if (ia) PetscValidPointer(ia, 6);
7868   if (ja) PetscValidPointer(ja, 7);
7869   if (done) PetscValidBoolPointer(done, 8);
7870   MatCheckPreallocated(mat, 1);
7871   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7872   else {
7873     if (done) *done = PETSC_TRUE;
7874     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7875     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7876     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7877   }
7878   PetscFunctionReturn(0);
7879 }
7880 
7881 /*@C
7882     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7883 
7884     Collective
7885 
7886     Input Parameters:
7887 +   mat - the matrix
7888 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7889 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7890                 symmetrized
7891 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7892                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7893                  always used.
7894 .   n - number of columns in the (possibly compressed) matrix
7895 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7896 -   ja - the row indices
7897 
7898     Output Parameters:
7899 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7900 
7901     Level: developer
7902 
7903 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7904 @*/
7905 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7906 {
7907   PetscFunctionBegin;
7908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7909   PetscValidType(mat, 1);
7910   PetscValidIntPointer(n, 5);
7911   if (ia) PetscValidPointer(ia, 6);
7912   if (ja) PetscValidPointer(ja, 7);
7913   PetscValidBoolPointer(done, 8);
7914   MatCheckPreallocated(mat, 1);
7915   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7916   else {
7917     *done = PETSC_TRUE;
7918     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7919   }
7920   PetscFunctionReturn(0);
7921 }
7922 
7923 /*@C
7924     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7925 
7926     Collective
7927 
7928     Input Parameters:
7929 +   mat - the matrix
7930 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7931 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7932 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7933                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7934                  always used.
7935 .   n - size of (possibly compressed) matrix
7936 .   ia - the row pointers
7937 -   ja - the column indices
7938 
7939     Output Parameters:
7940 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7941 
7942     Note:
7943     This routine zeros out n, ia, and ja. This is to prevent accidental
7944     us of the array after it has been restored. If you pass NULL, it will
7945     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7946 
7947     Level: developer
7948 
7949 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7950 @*/
7951 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7952 {
7953   PetscFunctionBegin;
7954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7955   PetscValidType(mat, 1);
7956   if (ia) PetscValidPointer(ia, 6);
7957   if (ja) PetscValidPointer(ja, 7);
7958   if (done) PetscValidBoolPointer(done, 8);
7959   MatCheckPreallocated(mat, 1);
7960 
7961   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7962   else {
7963     if (done) *done = PETSC_TRUE;
7964     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7965     if (n) *n = 0;
7966     if (ia) *ia = NULL;
7967     if (ja) *ja = NULL;
7968   }
7969   PetscFunctionReturn(0);
7970 }
7971 
7972 /*@C
7973     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7974 
7975     Collective on Mat
7976 
7977     Input Parameters:
7978 +   mat - the matrix
7979 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7980 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7981 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7982                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7983                  always used.
7984 
7985     Output Parameters:
7986 +   n - size of (possibly compressed) matrix
7987 .   ia - the column pointers
7988 .   ja - the row indices
7989 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7990 
7991     Level: developer
7992 
7993 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7994 @*/
7995 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7996 {
7997   PetscFunctionBegin;
7998   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7999   PetscValidType(mat, 1);
8000   if (ia) PetscValidPointer(ia, 6);
8001   if (ja) PetscValidPointer(ja, 7);
8002   PetscValidBoolPointer(done, 8);
8003   MatCheckPreallocated(mat, 1);
8004 
8005   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8006   else {
8007     *done = PETSC_TRUE;
8008     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8009     if (n) *n = 0;
8010     if (ia) *ia = NULL;
8011     if (ja) *ja = NULL;
8012   }
8013   PetscFunctionReturn(0);
8014 }
8015 
8016 /*@C
8017     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8018 
8019     Collective
8020 
8021     Input Parameters:
8022 +   mat - the matrix
8023 .   ncolors - max color value
8024 .   n   - number of entries in colorarray
8025 -   colorarray - array indicating color for each column
8026 
8027     Output Parameters:
8028 .   iscoloring - coloring generated using colorarray information
8029 
8030     Level: developer
8031 
8032 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8033 @*/
8034 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8035 {
8036   PetscFunctionBegin;
8037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8038   PetscValidType(mat, 1);
8039   PetscValidIntPointer(colorarray, 4);
8040   PetscValidPointer(iscoloring, 5);
8041   MatCheckPreallocated(mat, 1);
8042 
8043   if (!mat->ops->coloringpatch) {
8044     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8045   } else {
8046     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8047   }
8048   PetscFunctionReturn(0);
8049 }
8050 
8051 /*@
8052    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8053 
8054    Logically Collective
8055 
8056    Input Parameter:
8057 .  mat - the factored matrix to be reset
8058 
8059    Notes:
8060    This routine should be used only with factored matrices formed by in-place
8061    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8062    format).  This option can save memory, for example, when solving nonlinear
8063    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8064    ILU(0) preconditioner.
8065 
8066    Note that one can specify in-place ILU(0) factorization by calling
8067 .vb
8068      PCType(pc,PCILU);
8069      PCFactorSeUseInPlace(pc);
8070 .ve
8071    or by using the options -pc_type ilu -pc_factor_in_place
8072 
8073    In-place factorization ILU(0) can also be used as a local
8074    solver for the blocks within the block Jacobi or additive Schwarz
8075    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8076    for details on setting local solver options.
8077 
8078    Most users should employ the `KSP` interface for linear solvers
8079    instead of working directly with matrix algebra routines such as this.
8080    See, e.g., `KSPCreate()`.
8081 
8082    Level: developer
8083 
8084 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8085 @*/
8086 PetscErrorCode MatSetUnfactored(Mat mat)
8087 {
8088   PetscFunctionBegin;
8089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8090   PetscValidType(mat, 1);
8091   MatCheckPreallocated(mat, 1);
8092   mat->factortype = MAT_FACTOR_NONE;
8093   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8094   PetscUseTypeMethod(mat, setunfactored);
8095   PetscFunctionReturn(0);
8096 }
8097 
8098 /*MC
8099     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8100 
8101     Synopsis:
8102     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8103 
8104     Not collective
8105 
8106     Input Parameter:
8107 .   x - matrix
8108 
8109     Output Parameters:
8110 +   xx_v - the Fortran pointer to the array
8111 -   ierr - error code
8112 
8113     Example of Usage:
8114 .vb
8115       PetscScalar, pointer xx_v(:,:)
8116       ....
8117       call MatDenseGetArrayF90(x,xx_v,ierr)
8118       a = xx_v(3)
8119       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8120 .ve
8121 
8122     Level: advanced
8123 
8124 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8125 
8126 M*/
8127 
8128 /*MC
8129     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8130     accessed with `MatDenseGetArrayF90()`.
8131 
8132     Synopsis:
8133     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8134 
8135     Not collective
8136 
8137     Input Parameters:
8138 +   x - matrix
8139 -   xx_v - the Fortran90 pointer to the array
8140 
8141     Output Parameter:
8142 .   ierr - error code
8143 
8144     Example of Usage:
8145 .vb
8146        PetscScalar, pointer xx_v(:,:)
8147        ....
8148        call MatDenseGetArrayF90(x,xx_v,ierr)
8149        a = xx_v(3)
8150        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8151 .ve
8152 
8153     Level: advanced
8154 
8155 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8156 
8157 M*/
8158 
8159 /*MC
8160     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8161 
8162     Synopsis:
8163     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8164 
8165     Not collective
8166 
8167     Input Parameter:
8168 .   x - matrix
8169 
8170     Output Parameters:
8171 +   xx_v - the Fortran pointer to the array
8172 -   ierr - error code
8173 
8174     Example of Usage:
8175 .vb
8176       PetscScalar, pointer xx_v(:)
8177       ....
8178       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8179       a = xx_v(3)
8180       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8181 .ve
8182 
8183     Level: advanced
8184 
8185 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8186 
8187 M*/
8188 
8189 /*MC
8190     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8191     accessed with `MatSeqAIJGetArrayF90()`.
8192 
8193     Synopsis:
8194     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8195 
8196     Not collective
8197 
8198     Input Parameters:
8199 +   x - matrix
8200 -   xx_v - the Fortran90 pointer to the array
8201 
8202     Output Parameter:
8203 .   ierr - error code
8204 
8205     Example of Usage:
8206 .vb
8207        PetscScalar, pointer xx_v(:)
8208        ....
8209        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8210        a = xx_v(3)
8211        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8212 .ve
8213 
8214     Level: advanced
8215 
8216 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8217 
8218 M*/
8219 
8220 /*@
8221     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8222                       as the original matrix.
8223 
8224     Collective
8225 
8226     Input Parameters:
8227 +   mat - the original matrix
8228 .   isrow - parallel IS containing the rows this processor should obtain
8229 .   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.
8230 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8231 
8232     Output Parameter:
8233 .   newmat - the new submatrix, of the same type as the old
8234 
8235     Level: advanced
8236 
8237     Notes:
8238     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8239 
8240     Some matrix types place restrictions on the row and column indices, such
8241     as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8242     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8243 
8244     The index sets may not have duplicate entries.
8245 
8246       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8247    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8248    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8249    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8250    you are finished using it.
8251 
8252     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8253     the input matrix.
8254 
8255     If iscol is NULL then all columns are obtained (not supported in Fortran).
8256 
8257    Example usage:
8258    Consider the following 8x8 matrix with 34 non-zero values, that is
8259    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8260    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8261    as follows:
8262 
8263 .vb
8264             1  2  0  |  0  3  0  |  0  4
8265     Proc0   0  5  6  |  7  0  0  |  8  0
8266             9  0 10  | 11  0  0  | 12  0
8267     -------------------------------------
8268            13  0 14  | 15 16 17  |  0  0
8269     Proc1   0 18  0  | 19 20 21  |  0  0
8270             0  0  0  | 22 23  0  | 24  0
8271     -------------------------------------
8272     Proc2  25 26 27  |  0  0 28  | 29  0
8273            30  0  0  | 31 32 33  |  0 34
8274 .ve
8275 
8276     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8277 
8278 .vb
8279             2  0  |  0  3  0  |  0
8280     Proc0   5  6  |  7  0  0  |  8
8281     -------------------------------
8282     Proc1  18  0  | 19 20 21  |  0
8283     -------------------------------
8284     Proc2  26 27  |  0  0 28  | 29
8285             0  0  | 31 32 33  |  0
8286 .ve
8287 
8288 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8289 @*/
8290 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8291 {
8292   PetscMPIInt size;
8293   Mat        *local;
8294   IS          iscoltmp;
8295   PetscBool   flg;
8296 
8297   PetscFunctionBegin;
8298   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8299   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8300   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8301   PetscValidPointer(newmat, 5);
8302   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8303   PetscValidType(mat, 1);
8304   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8305   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8306 
8307   MatCheckPreallocated(mat, 1);
8308   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8309 
8310   if (!iscol || isrow == iscol) {
8311     PetscBool   stride;
8312     PetscMPIInt grabentirematrix = 0, grab;
8313     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8314     if (stride) {
8315       PetscInt first, step, n, rstart, rend;
8316       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8317       if (step == 1) {
8318         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8319         if (rstart == first) {
8320           PetscCall(ISGetLocalSize(isrow, &n));
8321           if (n == rend - rstart) grabentirematrix = 1;
8322         }
8323       }
8324     }
8325     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8326     if (grab) {
8327       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8328       if (cll == MAT_INITIAL_MATRIX) {
8329         *newmat = mat;
8330         PetscCall(PetscObjectReference((PetscObject)mat));
8331       }
8332       PetscFunctionReturn(0);
8333     }
8334   }
8335 
8336   if (!iscol) {
8337     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8338   } else {
8339     iscoltmp = iscol;
8340   }
8341 
8342   /* if original matrix is on just one processor then use submatrix generated */
8343   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8344     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8345     goto setproperties;
8346   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8347     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8348     *newmat = *local;
8349     PetscCall(PetscFree(local));
8350     goto setproperties;
8351   } else if (!mat->ops->createsubmatrix) {
8352     /* Create a new matrix type that implements the operation using the full matrix */
8353     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8354     switch (cll) {
8355     case MAT_INITIAL_MATRIX:
8356       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8357       break;
8358     case MAT_REUSE_MATRIX:
8359       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8360       break;
8361     default:
8362       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8363     }
8364     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8365     goto setproperties;
8366   }
8367 
8368   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8369   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8370   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8371 
8372 setproperties:
8373   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8374   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8375   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8376   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8377   PetscFunctionReturn(0);
8378 }
8379 
8380 /*@
8381    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8382 
8383    Not Collective
8384 
8385    Input Parameters:
8386 +  A - the matrix we wish to propagate options from
8387 -  B - the matrix we wish to propagate options to
8388 
8389    Level: beginner
8390 
8391    Note:
8392    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8393 
8394 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8395 @*/
8396 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8397 {
8398   PetscFunctionBegin;
8399   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8400   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8401   B->symmetry_eternal            = A->symmetry_eternal;
8402   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8403   B->symmetric                   = A->symmetric;
8404   B->structurally_symmetric      = A->structurally_symmetric;
8405   B->spd                         = A->spd;
8406   B->hermitian                   = A->hermitian;
8407   PetscFunctionReturn(0);
8408 }
8409 
8410 /*@
8411    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8412    used during the assembly process to store values that belong to
8413    other processors.
8414 
8415    Not Collective
8416 
8417    Input Parameters:
8418 +  mat   - the matrix
8419 .  size  - the initial size of the stash.
8420 -  bsize - the initial size of the block-stash(if used).
8421 
8422    Options Database Keys:
8423 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8424 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8425 
8426    Level: intermediate
8427 
8428    Notes:
8429      The block-stash is used for values set with `MatSetValuesBlocked()` while
8430      the stash is used for values set with `MatSetValues()`
8431 
8432      Run with the option -info and look for output of the form
8433      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8434      to determine the appropriate value, MM, to use for size and
8435      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8436      to determine the value, BMM to use for bsize
8437 
8438 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8439 @*/
8440 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8441 {
8442   PetscFunctionBegin;
8443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8444   PetscValidType(mat, 1);
8445   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8446   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8447   PetscFunctionReturn(0);
8448 }
8449 
8450 /*@
8451    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8452      the matrix
8453 
8454    Neighbor-wise Collective
8455 
8456    Input Parameters:
8457 +  mat   - the matrix
8458 .  x,y - the vectors
8459 -  w - where the result is stored
8460 
8461    Level: intermediate
8462 
8463    Notes:
8464     w may be the same vector as y.
8465 
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 MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
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   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8480   PetscCall(MatGetSize(A, &M, &N));
8481   PetscCall(VecGetSize(y, &Ny));
8482   if (M == Ny) {
8483     PetscCall(MatMultAdd(A, x, y, w));
8484   } else {
8485     PetscCall(MatMultTransposeAdd(A, x, y, w));
8486   }
8487   PetscFunctionReturn(0);
8488 }
8489 
8490 /*@
8491    MatInterpolate - y = A*x or A'*x depending on the shape of
8492      the matrix
8493 
8494    Neighbor-wise Collective
8495 
8496    Input Parameters:
8497 +  mat   - the matrix
8498 -  x,y - the vectors
8499 
8500    Level: intermediate
8501 
8502    Note:
8503     This allows one to use either the restriction or interpolation (its transpose)
8504     matrix to do the interpolation
8505 
8506 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8507 @*/
8508 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8509 {
8510   PetscInt M, N, Ny;
8511 
8512   PetscFunctionBegin;
8513   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8514   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8515   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8516   PetscCall(MatGetSize(A, &M, &N));
8517   PetscCall(VecGetSize(y, &Ny));
8518   if (M == Ny) {
8519     PetscCall(MatMult(A, x, y));
8520   } else {
8521     PetscCall(MatMultTranspose(A, x, y));
8522   }
8523   PetscFunctionReturn(0);
8524 }
8525 
8526 /*@
8527    MatRestrict - y = A*x or A'*x
8528 
8529    Neighbor-wise Collective on Mat
8530 
8531    Input Parameters:
8532 +  mat   - the matrix
8533 -  x,y - the vectors
8534 
8535    Level: intermediate
8536 
8537    Note:
8538     This allows one to use either the restriction or interpolation (its transpose)
8539     matrix to do the restriction
8540 
8541 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8542 @*/
8543 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8544 {
8545   PetscInt M, N, Ny;
8546 
8547   PetscFunctionBegin;
8548   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8549   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8550   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8551   PetscCall(MatGetSize(A, &M, &N));
8552   PetscCall(VecGetSize(y, &Ny));
8553   if (M == Ny) {
8554     PetscCall(MatMult(A, x, y));
8555   } else {
8556     PetscCall(MatMultTranspose(A, x, y));
8557   }
8558   PetscFunctionReturn(0);
8559 }
8560 
8561 /*@
8562    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8563 
8564    Neighbor-wise Collective on Mat
8565 
8566    Input Parameters:
8567 +  mat   - the matrix
8568 -  w, x - the input dense matrices
8569 
8570    Output Parameters:
8571 .  y - the output dense matrix
8572 
8573    Level: intermediate
8574 
8575    Note:
8576     This allows one to use either the restriction or interpolation (its transpose)
8577     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8578     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8579 
8580 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8581 @*/
8582 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8583 {
8584   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8585   PetscBool trans = PETSC_TRUE;
8586   MatReuse  reuse = MAT_INITIAL_MATRIX;
8587 
8588   PetscFunctionBegin;
8589   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8590   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8591   PetscValidType(x, 2);
8592   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8593   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8594   PetscCall(MatGetSize(A, &M, &N));
8595   PetscCall(MatGetSize(x, &Mx, &Nx));
8596   if (N == Mx) trans = PETSC_FALSE;
8597   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);
8598   Mo = trans ? N : M;
8599   if (*y) {
8600     PetscCall(MatGetSize(*y, &My, &Ny));
8601     if (Mo == My && Nx == Ny) {
8602       reuse = MAT_REUSE_MATRIX;
8603     } else {
8604       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);
8605       PetscCall(MatDestroy(y));
8606     }
8607   }
8608 
8609   if (w && *y == w) { /* this is to minimize changes in PCMG */
8610     PetscBool flg;
8611 
8612     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8613     if (w) {
8614       PetscInt My, Ny, Mw, Nw;
8615 
8616       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8617       PetscCall(MatGetSize(*y, &My, &Ny));
8618       PetscCall(MatGetSize(w, &Mw, &Nw));
8619       if (!flg || My != Mw || Ny != Nw) w = NULL;
8620     }
8621     if (!w) {
8622       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8623       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8624       PetscCall(PetscObjectDereference((PetscObject)w));
8625     } else {
8626       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8627     }
8628   }
8629   if (!trans) {
8630     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8631   } else {
8632     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8633   }
8634   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8635   PetscFunctionReturn(0);
8636 }
8637 
8638 /*@
8639    MatMatInterpolate - Y = A*X or A'*X
8640 
8641    Neighbor-wise Collective on Mat
8642 
8643    Input Parameters:
8644 +  mat   - the matrix
8645 -  x - the input dense matrix
8646 
8647    Output Parameters:
8648 .  y - the output dense matrix
8649 
8650    Level: intermediate
8651 
8652    Note:
8653     This allows one to use either the restriction or interpolation (its transpose)
8654     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8655     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8656 
8657 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8658 @*/
8659 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8660 {
8661   PetscFunctionBegin;
8662   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8663   PetscFunctionReturn(0);
8664 }
8665 
8666 /*@
8667    MatMatRestrict - Y = A*X or A'*X
8668 
8669    Neighbor-wise Collective on Mat
8670 
8671    Input Parameters:
8672 +  mat   - the matrix
8673 -  x - the input dense matrix
8674 
8675    Output Parameters:
8676 .  y - the output dense matrix
8677 
8678    Level: intermediate
8679 
8680    Note:
8681     This allows one to use either the restriction or interpolation (its transpose)
8682     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8683     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8684 
8685 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8686 @*/
8687 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8688 {
8689   PetscFunctionBegin;
8690   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8691   PetscFunctionReturn(0);
8692 }
8693 
8694 /*@
8695    MatGetNullSpace - retrieves the null space of a matrix.
8696 
8697    Logically Collective
8698 
8699    Input Parameters:
8700 +  mat - the matrix
8701 -  nullsp - the null space object
8702 
8703    Level: developer
8704 
8705 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8706 @*/
8707 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8708 {
8709   PetscFunctionBegin;
8710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8711   PetscValidPointer(nullsp, 2);
8712   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8713   PetscFunctionReturn(0);
8714 }
8715 
8716 /*@
8717    MatSetNullSpace - attaches a null space to a matrix.
8718 
8719    Logically Collective
8720 
8721    Input Parameters:
8722 +  mat - the matrix
8723 -  nullsp - the null space object
8724 
8725    Level: advanced
8726 
8727    Notes:
8728       This null space is used by the `KSP` linear solvers to solve singular systems.
8729 
8730       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
8731 
8732       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
8733       to zero but the linear system will still be solved in a least squares sense.
8734 
8735       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8736    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).
8737    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
8738    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
8739    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).
8740    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8741 
8742     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8743     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8744     routine also automatically calls `MatSetTransposeNullSpace()`.
8745 
8746     The user should call `MatNullSpaceDestroy()`.
8747 
8748 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8749           `KSPSetPCSide()`
8750 @*/
8751 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8752 {
8753   PetscFunctionBegin;
8754   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8755   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8756   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8757   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8758   mat->nullsp = nullsp;
8759   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8760   PetscFunctionReturn(0);
8761 }
8762 
8763 /*@
8764    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8765 
8766    Logically Collective
8767 
8768    Input Parameters:
8769 +  mat - the matrix
8770 -  nullsp - the null space object
8771 
8772    Level: developer
8773 
8774 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8775 @*/
8776 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8777 {
8778   PetscFunctionBegin;
8779   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8780   PetscValidType(mat, 1);
8781   PetscValidPointer(nullsp, 2);
8782   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8783   PetscFunctionReturn(0);
8784 }
8785 
8786 /*@
8787    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8788 
8789    Logically Collective
8790 
8791    Input Parameters:
8792 +  mat - the matrix
8793 -  nullsp - the null space object
8794 
8795    Level: advanced
8796 
8797    Notes:
8798    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8799 
8800    See `MatSetNullSpace()`
8801 
8802 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8803 @*/
8804 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8805 {
8806   PetscFunctionBegin;
8807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8808   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8809   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8810   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8811   mat->transnullsp = nullsp;
8812   PetscFunctionReturn(0);
8813 }
8814 
8815 /*@
8816    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8817         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8818 
8819    Logically Collective
8820 
8821    Input Parameters:
8822 +  mat - the matrix
8823 -  nullsp - the null space object
8824 
8825    Level: advanced
8826 
8827    Notes:
8828    Overwrites any previous near null space that may have been attached
8829 
8830    You can remove the null space by calling this routine with an nullsp of NULL
8831 
8832 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8833 @*/
8834 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8835 {
8836   PetscFunctionBegin;
8837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8838   PetscValidType(mat, 1);
8839   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8840   MatCheckPreallocated(mat, 1);
8841   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8842   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8843   mat->nearnullsp = nullsp;
8844   PetscFunctionReturn(0);
8845 }
8846 
8847 /*@
8848    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8849 
8850    Not Collective
8851 
8852    Input Parameter:
8853 .  mat - the matrix
8854 
8855    Output Parameter:
8856 .  nullsp - the null space object, NULL if not set
8857 
8858    Level: advanced
8859 
8860 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8861 @*/
8862 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8863 {
8864   PetscFunctionBegin;
8865   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8866   PetscValidType(mat, 1);
8867   PetscValidPointer(nullsp, 2);
8868   MatCheckPreallocated(mat, 1);
8869   *nullsp = mat->nearnullsp;
8870   PetscFunctionReturn(0);
8871 }
8872 
8873 /*@C
8874    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8875 
8876    Collective
8877 
8878    Input Parameters:
8879 +  mat - the matrix
8880 .  row - row/column permutation
8881 .  fill - expected fill factor >= 1.0
8882 -  level - level of fill, for ICC(k)
8883 
8884    Notes:
8885    Probably really in-place only when level of fill is zero, otherwise allocates
8886    new space to store factored matrix and deletes previous memory.
8887 
8888    Most users should employ the `KSP` interface for linear solvers
8889    instead of working directly with matrix algebra routines such as this.
8890    See, e.g., `KSPCreate()`.
8891 
8892    Level: developer
8893 
8894    Developer Note:
8895    The Fortran interface is not autogenerated as the
8896    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8897 
8898 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8899 @*/
8900 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8901 {
8902   PetscFunctionBegin;
8903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8904   PetscValidType(mat, 1);
8905   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8906   PetscValidPointer(info, 3);
8907   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8908   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8909   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8910   MatCheckPreallocated(mat, 1);
8911   PetscUseTypeMethod(mat, iccfactor, row, info);
8912   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8913   PetscFunctionReturn(0);
8914 }
8915 
8916 /*@
8917    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8918          ghosted ones.
8919 
8920    Not Collective
8921 
8922    Input Parameters:
8923 +  mat - the matrix
8924 -  diag - the diagonal values, including ghost ones
8925 
8926    Level: developer
8927 
8928    Notes:
8929     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8930 
8931     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8932 
8933 .seealso: `MatDiagonalScale()`
8934 @*/
8935 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8936 {
8937   PetscMPIInt size;
8938 
8939   PetscFunctionBegin;
8940   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8941   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8942   PetscValidType(mat, 1);
8943 
8944   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8945   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8946   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8947   if (size == 1) {
8948     PetscInt n, m;
8949     PetscCall(VecGetSize(diag, &n));
8950     PetscCall(MatGetSize(mat, NULL, &m));
8951     if (m == n) {
8952       PetscCall(MatDiagonalScale(mat, NULL, diag));
8953     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8954   } else {
8955     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8956   }
8957   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8958   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8959   PetscFunctionReturn(0);
8960 }
8961 
8962 /*@
8963    MatGetInertia - Gets the inertia from a factored matrix
8964 
8965    Collective
8966 
8967    Input Parameter:
8968 .  mat - the matrix
8969 
8970    Output Parameters:
8971 +   nneg - number of negative eigenvalues
8972 .   nzero - number of zero eigenvalues
8973 -   npos - number of positive eigenvalues
8974 
8975    Level: advanced
8976 
8977    Note:
8978     Matrix must have been factored by `MatCholeskyFactor()`
8979 
8980 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8981 @*/
8982 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8983 {
8984   PetscFunctionBegin;
8985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8986   PetscValidType(mat, 1);
8987   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8988   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8989   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8990   PetscFunctionReturn(0);
8991 }
8992 
8993 /* ----------------------------------------------------------------*/
8994 /*@C
8995    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8996 
8997    Neighbor-wise Collective
8998 
8999    Input Parameters:
9000 +  mat - the factored matrix obtained with `MatGetFactor()`
9001 -  b - the right-hand-side vectors
9002 
9003    Output Parameter:
9004 .  x - the result vectors
9005 
9006    Note:
9007    The vectors b and x cannot be the same.  I.e., one cannot
9008    call `MatSolves`(A,x,x).
9009 
9010    Level: developer
9011 
9012 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9013 @*/
9014 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9015 {
9016   PetscFunctionBegin;
9017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9018   PetscValidType(mat, 1);
9019   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9020   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9021   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
9022 
9023   MatCheckPreallocated(mat, 1);
9024   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9025   PetscUseTypeMethod(mat, solves, b, x);
9026   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9027   PetscFunctionReturn(0);
9028 }
9029 
9030 /*@
9031    MatIsSymmetric - Test whether a matrix is symmetric
9032 
9033    Collective
9034 
9035    Input Parameters:
9036 +  A - the matrix to test
9037 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9038 
9039    Output Parameters:
9040 .  flg - the result
9041 
9042    Notes:
9043     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9044 
9045     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9046 
9047     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9048     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9049 
9050    Level: intermediate
9051 
9052 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9053           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9054 @*/
9055 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9056 {
9057   PetscFunctionBegin;
9058   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9059   PetscValidBoolPointer(flg, 3);
9060 
9061   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9062   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9063   else {
9064     if (!A->ops->issymmetric) {
9065       MatType mattype;
9066       PetscCall(MatGetType(A, &mattype));
9067       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9068     }
9069     PetscUseTypeMethod(A, issymmetric, tol, flg);
9070     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9071   }
9072   PetscFunctionReturn(0);
9073 }
9074 
9075 /*@
9076    MatIsHermitian - Test whether a matrix is Hermitian
9077 
9078    Collective on Mat
9079 
9080    Input Parameters:
9081 +  A - the matrix to test
9082 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9083 
9084    Output Parameters:
9085 .  flg - the result
9086 
9087    Level: intermediate
9088 
9089    Notes:
9090     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9091 
9092     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9093 
9094     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9095     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9096 
9097 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9098           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9099 @*/
9100 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9101 {
9102   PetscFunctionBegin;
9103   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9104   PetscValidBoolPointer(flg, 3);
9105 
9106   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9107   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9108   else {
9109     if (!A->ops->ishermitian) {
9110       MatType mattype;
9111       PetscCall(MatGetType(A, &mattype));
9112       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9113     }
9114     PetscUseTypeMethod(A, ishermitian, tol, flg);
9115     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9116   }
9117   PetscFunctionReturn(0);
9118 }
9119 
9120 /*@
9121    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9122 
9123    Not Collective
9124 
9125    Input Parameter:
9126 .  A - the matrix to check
9127 
9128    Output Parameters:
9129 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9130 -  flg - the result (only valid if set is `PETSC_TRUE`)
9131 
9132    Level: advanced
9133 
9134    Notes:
9135    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9136    if you want it explicitly checked
9137 
9138     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9139     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9140 
9141 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9142 @*/
9143 PetscErrorCode MatIsSymmetricKnown(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->symmetric != PETSC_BOOL3_UNKNOWN) {
9150     *set = PETSC_TRUE;
9151     *flg = PetscBool3ToBool(A->symmetric);
9152   } else {
9153     *set = PETSC_FALSE;
9154   }
9155   PetscFunctionReturn(0);
9156 }
9157 
9158 /*@
9159    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite 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 symmetric positive definite 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`).
9174 
9175    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9176    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9177 
9178 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9179 @*/
9180 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9181 {
9182   PetscFunctionBegin;
9183   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9184   PetscValidBoolPointer(set, 2);
9185   PetscValidBoolPointer(flg, 3);
9186   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9187     *set = PETSC_TRUE;
9188     *flg = PetscBool3ToBool(A->spd);
9189   } else {
9190     *set = PETSC_FALSE;
9191   }
9192   PetscFunctionReturn(0);
9193 }
9194 
9195 /*@
9196    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9197 
9198    Not Collective
9199 
9200    Input Parameter:
9201 .  A - the matrix to check
9202 
9203    Output Parameters:
9204 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9205 -  flg - the result (only valid if set is `PETSC_TRUE`)
9206 
9207    Level: advanced
9208 
9209    Notes:
9210    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9211    if you want it explicitly checked
9212 
9213    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9214    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9215 
9216 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9217 @*/
9218 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9219 {
9220   PetscFunctionBegin;
9221   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9222   PetscValidBoolPointer(set, 2);
9223   PetscValidBoolPointer(flg, 3);
9224   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9225     *set = PETSC_TRUE;
9226     *flg = PetscBool3ToBool(A->hermitian);
9227   } else {
9228     *set = PETSC_FALSE;
9229   }
9230   PetscFunctionReturn(0);
9231 }
9232 
9233 /*@
9234    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9235 
9236    Collective on Mat
9237 
9238    Input Parameter:
9239 .  A - the matrix to test
9240 
9241    Output Parameters:
9242 .  flg - the result
9243 
9244    Notes:
9245    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9246 
9247    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
9248    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9249 
9250    Level: intermediate
9251 
9252 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9253 @*/
9254 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9255 {
9256   PetscFunctionBegin;
9257   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9258   PetscValidBoolPointer(flg, 2);
9259   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9260     *flg = PetscBool3ToBool(A->structurally_symmetric);
9261   } else {
9262     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9263     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9264   }
9265   PetscFunctionReturn(0);
9266 }
9267 
9268 /*@
9269    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9270 
9271    Not Collective
9272 
9273    Input Parameter:
9274 .  A - the matrix to check
9275 
9276    Output Parameters:
9277 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9278 -  flg - the result (only valid if set is PETSC_TRUE)
9279 
9280    Level: advanced
9281 
9282    Notes:
9283    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
9284    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9285 
9286    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9287 
9288 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9289 @*/
9290 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9291 {
9292   PetscFunctionBegin;
9293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9294   PetscValidBoolPointer(set, 2);
9295   PetscValidBoolPointer(flg, 3);
9296   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9297     *set = PETSC_TRUE;
9298     *flg = PetscBool3ToBool(A->structurally_symmetric);
9299   } else {
9300     *set = PETSC_FALSE;
9301   }
9302   PetscFunctionReturn(0);
9303 }
9304 
9305 /*@
9306    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9307        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9308 
9309     Not collective
9310 
9311    Input Parameter:
9312 .   mat - the matrix
9313 
9314    Output Parameters:
9315 +   nstash   - the size of the stash
9316 .   reallocs - the number of additional mallocs incurred.
9317 .   bnstash   - the size of the block stash
9318 -   breallocs - the number of additional mallocs incurred.in the block stash
9319 
9320    Level: advanced
9321 
9322 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9323 @*/
9324 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9325 {
9326   PetscFunctionBegin;
9327   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9328   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9329   PetscFunctionReturn(0);
9330 }
9331 
9332 /*@C
9333    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9334    parallel layout, `PetscLayout` for rows and columns
9335 
9336    Collective
9337 
9338    Input Parameter:
9339 .  mat - the matrix
9340 
9341    Output Parameters:
9342 +   right - (optional) vector that the matrix can be multiplied against
9343 -   left - (optional) vector that the matrix vector product can be stored in
9344 
9345    Notes:
9346     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()`.
9347 
9348     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9349 
9350   Level: advanced
9351 
9352 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9353 @*/
9354 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9355 {
9356   PetscFunctionBegin;
9357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9358   PetscValidType(mat, 1);
9359   if (mat->ops->getvecs) {
9360     PetscUseTypeMethod(mat, getvecs, right, left);
9361   } else {
9362     PetscInt rbs, cbs;
9363     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9364     if (right) {
9365       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9366       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9367       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9368       PetscCall(VecSetBlockSize(*right, cbs));
9369       PetscCall(VecSetType(*right, mat->defaultvectype));
9370 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9371       if (mat->boundtocpu && mat->bindingpropagates) {
9372         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9373         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9374       }
9375 #endif
9376       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9377     }
9378     if (left) {
9379       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9380       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9381       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9382       PetscCall(VecSetBlockSize(*left, rbs));
9383       PetscCall(VecSetType(*left, mat->defaultvectype));
9384 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9385       if (mat->boundtocpu && mat->bindingpropagates) {
9386         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9387         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9388       }
9389 #endif
9390       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9391     }
9392   }
9393   PetscFunctionReturn(0);
9394 }
9395 
9396 /*@C
9397    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9398      with default values.
9399 
9400    Not Collective
9401 
9402    Input Parameters:
9403 .    info - the `MatFactorInfo` data structure
9404 
9405    Notes:
9406     The solvers are generally used through the `KSP` and `PC` objects, for example
9407           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9408 
9409     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9410 
9411    Level: developer
9412 
9413    Developer Note:
9414    The Fortran interface is not autogenerated as the
9415    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9416 
9417 .seealso: `MatGetFactor()`, `MatFactorInfo`
9418 @*/
9419 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9420 {
9421   PetscFunctionBegin;
9422   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9423   PetscFunctionReturn(0);
9424 }
9425 
9426 /*@
9427    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9428 
9429    Collective
9430 
9431    Input Parameters:
9432 +  mat - the factored matrix
9433 -  is - the index set defining the Schur indices (0-based)
9434 
9435    Notes:
9436     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9437 
9438    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9439 
9440    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9441 
9442    Level: advanced
9443 
9444 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9445           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9446 
9447 @*/
9448 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9449 {
9450   PetscErrorCode (*f)(Mat, IS);
9451 
9452   PetscFunctionBegin;
9453   PetscValidType(mat, 1);
9454   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9455   PetscValidType(is, 2);
9456   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9457   PetscCheckSameComm(mat, 1, is, 2);
9458   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9459   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9460   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9461   PetscCall(MatDestroy(&mat->schur));
9462   PetscCall((*f)(mat, is));
9463   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9464   PetscFunctionReturn(0);
9465 }
9466 
9467 /*@
9468   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9469 
9470    Logically Collective
9471 
9472    Input Parameters:
9473 +  F - the factored matrix obtained by calling `MatGetFactor()`
9474 .  S - location where to return the Schur complement, can be NULL
9475 -  status - the status of the Schur complement matrix, can be NULL
9476 
9477    Notes:
9478    You must call `MatFactorSetSchurIS()` before calling this routine.
9479 
9480    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9481 
9482    The routine provides a copy of the Schur matrix stored within the solver data structures.
9483    The caller must destroy the object when it is no longer needed.
9484    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9485 
9486    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)
9487 
9488    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9489 
9490    Developer Note:
9491     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9492    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9493 
9494    Level: advanced
9495 
9496 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9497 @*/
9498 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9499 {
9500   PetscFunctionBegin;
9501   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9502   if (S) PetscValidPointer(S, 2);
9503   if (status) PetscValidPointer(status, 3);
9504   if (S) {
9505     PetscErrorCode (*f)(Mat, Mat *);
9506 
9507     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9508     if (f) {
9509       PetscCall((*f)(F, S));
9510     } else {
9511       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9512     }
9513   }
9514   if (status) *status = F->schur_status;
9515   PetscFunctionReturn(0);
9516 }
9517 
9518 /*@
9519   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9520 
9521    Logically Collective
9522 
9523    Input Parameters:
9524 +  F - the factored matrix obtained by calling `MatGetFactor()`
9525 .  *S - location where to return the Schur complement, can be NULL
9526 -  status - the status of the Schur complement matrix, can be NULL
9527 
9528    Notes:
9529    You must call `MatFactorSetSchurIS()` before calling this routine.
9530 
9531    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9532 
9533    The routine returns a the Schur Complement stored within the data strutures of the solver.
9534 
9535    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9536 
9537    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9538 
9539    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9540 
9541    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9542 
9543    Level: advanced
9544 
9545 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9546 @*/
9547 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9548 {
9549   PetscFunctionBegin;
9550   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9551   if (S) PetscValidPointer(S, 2);
9552   if (status) PetscValidPointer(status, 3);
9553   if (S) *S = F->schur;
9554   if (status) *status = F->schur_status;
9555   PetscFunctionReturn(0);
9556 }
9557 
9558 /*@
9559   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9560 
9561    Logically Collective
9562 
9563    Input Parameters:
9564 +  F - the factored matrix obtained by calling `MatGetFactor()`
9565 .  *S - location where the Schur complement is stored
9566 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9567 
9568    Level: advanced
9569 
9570 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9571 @*/
9572 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9573 {
9574   PetscFunctionBegin;
9575   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9576   if (S) {
9577     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9578     *S = NULL;
9579   }
9580   F->schur_status = status;
9581   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9582   PetscFunctionReturn(0);
9583 }
9584 
9585 /*@
9586   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9587 
9588    Logically Collective
9589 
9590    Input Parameters:
9591 +  F - the factored matrix obtained by calling `MatGetFactor()`
9592 .  rhs - location where the right hand side of the Schur complement system is stored
9593 -  sol - location where the solution of the Schur complement system has to be returned
9594 
9595    Notes:
9596    The sizes of the vectors should match the size of the Schur complement
9597 
9598    Must be called after `MatFactorSetSchurIS()`
9599 
9600    Level: advanced
9601 
9602 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9603 @*/
9604 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9605 {
9606   PetscFunctionBegin;
9607   PetscValidType(F, 1);
9608   PetscValidType(rhs, 2);
9609   PetscValidType(sol, 3);
9610   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9611   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9612   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9613   PetscCheckSameComm(F, 1, rhs, 2);
9614   PetscCheckSameComm(F, 1, sol, 3);
9615   PetscCall(MatFactorFactorizeSchurComplement(F));
9616   switch (F->schur_status) {
9617   case MAT_FACTOR_SCHUR_FACTORED:
9618     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9619     break;
9620   case MAT_FACTOR_SCHUR_INVERTED:
9621     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9622     break;
9623   default:
9624     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9625   }
9626   PetscFunctionReturn(0);
9627 }
9628 
9629 /*@
9630   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9631 
9632    Logically Collective
9633 
9634    Input Parameters:
9635 +  F - the factored matrix obtained by calling `MatGetFactor()`
9636 .  rhs - location where the right hand side of the Schur complement system is stored
9637 -  sol - location where the solution of the Schur complement system has to be returned
9638 
9639    Notes:
9640    The sizes of the vectors should match the size of the Schur complement
9641 
9642    Must be called after `MatFactorSetSchurIS()`
9643 
9644    Level: advanced
9645 
9646 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9647 @*/
9648 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9649 {
9650   PetscFunctionBegin;
9651   PetscValidType(F, 1);
9652   PetscValidType(rhs, 2);
9653   PetscValidType(sol, 3);
9654   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9655   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9656   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9657   PetscCheckSameComm(F, 1, rhs, 2);
9658   PetscCheckSameComm(F, 1, sol, 3);
9659   PetscCall(MatFactorFactorizeSchurComplement(F));
9660   switch (F->schur_status) {
9661   case MAT_FACTOR_SCHUR_FACTORED:
9662     PetscCall(MatSolve(F->schur, rhs, sol));
9663     break;
9664   case MAT_FACTOR_SCHUR_INVERTED:
9665     PetscCall(MatMult(F->schur, rhs, sol));
9666     break;
9667   default:
9668     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9669   }
9670   PetscFunctionReturn(0);
9671 }
9672 
9673 /*@
9674   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9675 
9676    Logically Collective on F
9677 
9678    Input Parameters:
9679 .  F - the factored matrix obtained by calling `MatGetFactor()`
9680 
9681    Notes:
9682     Must be called after `MatFactorSetSchurIS()`.
9683 
9684    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9685 
9686    Level: advanced
9687 
9688 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9689 @*/
9690 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9691 {
9692   PetscFunctionBegin;
9693   PetscValidType(F, 1);
9694   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9695   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9696   PetscCall(MatFactorFactorizeSchurComplement(F));
9697   PetscCall(MatFactorInvertSchurComplement_Private(F));
9698   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9699   PetscFunctionReturn(0);
9700 }
9701 
9702 /*@
9703   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9704 
9705    Logically Collective
9706 
9707    Input Parameters:
9708 .  F - the factored matrix obtained by calling `MatGetFactor()`
9709 
9710    Note:
9711     Must be called after `MatFactorSetSchurIS()`
9712 
9713    Level: advanced
9714 
9715 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9716 @*/
9717 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9718 {
9719   PetscFunctionBegin;
9720   PetscValidType(F, 1);
9721   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9722   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9723   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9724   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9725   PetscFunctionReturn(0);
9726 }
9727 
9728 /*@
9729    MatPtAP - Creates the matrix product C = P^T * A * P
9730 
9731    Neighbor-wise Collective on A
9732 
9733    Input Parameters:
9734 +  A - the matrix
9735 .  P - the projection matrix
9736 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9737 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9738           if the result is a dense matrix this is irrelevant
9739 
9740    Output Parameters:
9741 .  C - the product matrix
9742 
9743    Notes:
9744    C will be created and must be destroyed by the user with `MatDestroy()`.
9745 
9746    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9747 
9748    Developer Note:
9749    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9750 
9751    Level: intermediate
9752 
9753 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9754 @*/
9755 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9756 {
9757   PetscFunctionBegin;
9758   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9759   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9760 
9761   if (scall == MAT_INITIAL_MATRIX) {
9762     PetscCall(MatProductCreate(A, P, NULL, C));
9763     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9764     PetscCall(MatProductSetAlgorithm(*C, "default"));
9765     PetscCall(MatProductSetFill(*C, fill));
9766 
9767     (*C)->product->api_user = PETSC_TRUE;
9768     PetscCall(MatProductSetFromOptions(*C));
9769     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);
9770     PetscCall(MatProductSymbolic(*C));
9771   } else { /* scall == MAT_REUSE_MATRIX */
9772     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9773   }
9774 
9775   PetscCall(MatProductNumeric(*C));
9776   (*C)->symmetric = A->symmetric;
9777   (*C)->spd       = A->spd;
9778   PetscFunctionReturn(0);
9779 }
9780 
9781 /*@
9782    MatRARt - Creates the matrix product C = R * A * R^T
9783 
9784    Neighbor-wise Collective on A
9785 
9786    Input Parameters:
9787 +  A - the matrix
9788 .  R - the projection matrix
9789 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9790 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9791           if the result is a dense matrix this is irrelevant
9792 
9793    Output Parameters:
9794 .  C - the product matrix
9795 
9796    Notes:
9797    C will be created and must be destroyed by the user with `MatDestroy()`.
9798 
9799    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9800 
9801    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9802    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9803    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9804    We recommend using MatPtAP().
9805 
9806    Level: intermediate
9807 
9808 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9809 @*/
9810 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9811 {
9812   PetscFunctionBegin;
9813   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9814   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9815 
9816   if (scall == MAT_INITIAL_MATRIX) {
9817     PetscCall(MatProductCreate(A, R, NULL, C));
9818     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9819     PetscCall(MatProductSetAlgorithm(*C, "default"));
9820     PetscCall(MatProductSetFill(*C, fill));
9821 
9822     (*C)->product->api_user = PETSC_TRUE;
9823     PetscCall(MatProductSetFromOptions(*C));
9824     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);
9825     PetscCall(MatProductSymbolic(*C));
9826   } else { /* scall == MAT_REUSE_MATRIX */
9827     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9828   }
9829 
9830   PetscCall(MatProductNumeric(*C));
9831   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9832   PetscFunctionReturn(0);
9833 }
9834 
9835 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9836 {
9837   PetscFunctionBegin;
9838   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9839 
9840   if (scall == MAT_INITIAL_MATRIX) {
9841     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9842     PetscCall(MatProductCreate(A, B, NULL, C));
9843     PetscCall(MatProductSetType(*C, ptype));
9844     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9845     PetscCall(MatProductSetFill(*C, fill));
9846 
9847     (*C)->product->api_user = PETSC_TRUE;
9848     PetscCall(MatProductSetFromOptions(*C));
9849     PetscCall(MatProductSymbolic(*C));
9850   } else { /* scall == MAT_REUSE_MATRIX */
9851     Mat_Product *product = (*C)->product;
9852     PetscBool    isdense;
9853 
9854     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9855     if (isdense && product && product->type != ptype) {
9856       PetscCall(MatProductClear(*C));
9857       product = NULL;
9858     }
9859     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9860     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9861       if (isdense) {
9862         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9863         product           = (*C)->product;
9864         product->fill     = fill;
9865         product->api_user = PETSC_TRUE;
9866         product->clear    = PETSC_TRUE;
9867 
9868         PetscCall(MatProductSetType(*C, ptype));
9869         PetscCall(MatProductSetFromOptions(*C));
9870         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);
9871         PetscCall(MatProductSymbolic(*C));
9872       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9873     } else { /* user may change input matrices A or B when REUSE */
9874       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9875     }
9876   }
9877   PetscCall(MatProductNumeric(*C));
9878   PetscFunctionReturn(0);
9879 }
9880 
9881 /*@
9882    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9883 
9884    Neighbor-wise Collective on A
9885 
9886    Input Parameters:
9887 +  A - the left matrix
9888 .  B - the right matrix
9889 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9890 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9891           if the result is a dense matrix this is irrelevant
9892 
9893    Output Parameters:
9894 .  C - the product matrix
9895 
9896    Notes:
9897    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9898 
9899    `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
9900    call to this function with `MAT_INITIAL_MATRIX`.
9901 
9902    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9903 
9904    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`,
9905    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9906 
9907    Example of Usage:
9908 .vb
9909      MatProductCreate(A,B,NULL,&C);
9910      MatProductSetType(C,MATPRODUCT_AB);
9911      MatProductSymbolic(C);
9912      MatProductNumeric(C); // compute C=A * B
9913      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9914      MatProductNumeric(C);
9915      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9916      MatProductNumeric(C);
9917 .ve
9918 
9919    Level: intermediate
9920 
9921 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9922 @*/
9923 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9924 {
9925   PetscFunctionBegin;
9926   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9927   PetscFunctionReturn(0);
9928 }
9929 
9930 /*@
9931    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9932 
9933    Neighbor-wise Collective on A
9934 
9935    Input Parameters:
9936 +  A - the left matrix
9937 .  B - the right matrix
9938 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9939 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9940 
9941    Output Parameters:
9942 .  C - the product matrix
9943 
9944    Notes:
9945    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9946 
9947    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9948 
9949    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9950    actually needed.
9951 
9952    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9953    and for pairs of `MATMPIDENSE` matrices.
9954 
9955    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9956 
9957    Options Database Keys:
9958 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9959               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9960               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9961 
9962    Level: intermediate
9963 
9964 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9965 @*/
9966 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9967 {
9968   PetscFunctionBegin;
9969   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9970   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9971   PetscFunctionReturn(0);
9972 }
9973 
9974 /*@
9975    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9976 
9977    Neighbor-wise Collective on A
9978 
9979    Input Parameters:
9980 +  A - the left matrix
9981 .  B - the right matrix
9982 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9983 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9984 
9985    Output Parameters:
9986 .  C - the product matrix
9987 
9988    Notes:
9989    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9990 
9991    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9992 
9993    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9994 
9995    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9996    actually needed.
9997 
9998    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9999    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10000 
10001    Level: intermediate
10002 
10003 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10004 @*/
10005 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10006 {
10007   PetscFunctionBegin;
10008   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10009   PetscFunctionReturn(0);
10010 }
10011 
10012 /*@
10013    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10014 
10015    Neighbor-wise Collective on A
10016 
10017    Input Parameters:
10018 +  A - the left matrix
10019 .  B - the middle matrix
10020 .  C - the right matrix
10021 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10022 -  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
10023           if the result is a dense matrix this is irrelevant
10024 
10025    Output Parameters:
10026 .  D - the product matrix
10027 
10028    Notes:
10029    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10030 
10031    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10032 
10033    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10034 
10035    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10036    actually needed.
10037 
10038    If you have many matrices with the same non-zero structure to multiply, you
10039    should use `MAT_REUSE_MATRIX` in all calls but the first
10040 
10041    Level: intermediate
10042 
10043 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10044 @*/
10045 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10046 {
10047   PetscFunctionBegin;
10048   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10049   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10050 
10051   if (scall == MAT_INITIAL_MATRIX) {
10052     PetscCall(MatProductCreate(A, B, C, D));
10053     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10054     PetscCall(MatProductSetAlgorithm(*D, "default"));
10055     PetscCall(MatProductSetFill(*D, fill));
10056 
10057     (*D)->product->api_user = PETSC_TRUE;
10058     PetscCall(MatProductSetFromOptions(*D));
10059     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,
10060                ((PetscObject)C)->type_name);
10061     PetscCall(MatProductSymbolic(*D));
10062   } else { /* user may change input matrices when REUSE */
10063     PetscCall(MatProductReplaceMats(A, B, C, *D));
10064   }
10065   PetscCall(MatProductNumeric(*D));
10066   PetscFunctionReturn(0);
10067 }
10068 
10069 /*@
10070    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10071 
10072    Collective
10073 
10074    Input Parameters:
10075 +  mat - the matrix
10076 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10077 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10078 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10079 
10080    Output Parameter:
10081 .  matredundant - redundant matrix
10082 
10083    Notes:
10084    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10085    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10086 
10087    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10088    calling it.
10089 
10090    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10091 
10092    Level: advanced
10093 
10094 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10095 @*/
10096 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10097 {
10098   MPI_Comm       comm;
10099   PetscMPIInt    size;
10100   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10101   Mat_Redundant *redund     = NULL;
10102   PetscSubcomm   psubcomm   = NULL;
10103   MPI_Comm       subcomm_in = subcomm;
10104   Mat           *matseq;
10105   IS             isrow, iscol;
10106   PetscBool      newsubcomm = PETSC_FALSE;
10107 
10108   PetscFunctionBegin;
10109   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10110   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10111     PetscValidPointer(*matredundant, 5);
10112     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10113   }
10114 
10115   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10116   if (size == 1 || nsubcomm == 1) {
10117     if (reuse == MAT_INITIAL_MATRIX) {
10118       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10119     } else {
10120       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");
10121       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10122     }
10123     PetscFunctionReturn(0);
10124   }
10125 
10126   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10127   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10128   MatCheckPreallocated(mat, 1);
10129 
10130   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10131   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10132     /* create psubcomm, then get subcomm */
10133     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10134     PetscCallMPI(MPI_Comm_size(comm, &size));
10135     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10136 
10137     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10138     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10139     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10140     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10141     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10142     newsubcomm = PETSC_TRUE;
10143     PetscCall(PetscSubcommDestroy(&psubcomm));
10144   }
10145 
10146   /* get isrow, iscol and a local sequential matrix matseq[0] */
10147   if (reuse == MAT_INITIAL_MATRIX) {
10148     mloc_sub = PETSC_DECIDE;
10149     nloc_sub = PETSC_DECIDE;
10150     if (bs < 1) {
10151       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10152       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10153     } else {
10154       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10155       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10156     }
10157     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10158     rstart = rend - mloc_sub;
10159     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10160     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10161   } else { /* reuse == MAT_REUSE_MATRIX */
10162     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");
10163     /* retrieve subcomm */
10164     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10165     redund = (*matredundant)->redundant;
10166     isrow  = redund->isrow;
10167     iscol  = redund->iscol;
10168     matseq = redund->matseq;
10169   }
10170   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10171 
10172   /* get matredundant over subcomm */
10173   if (reuse == MAT_INITIAL_MATRIX) {
10174     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10175 
10176     /* create a supporting struct and attach it to C for reuse */
10177     PetscCall(PetscNew(&redund));
10178     (*matredundant)->redundant = redund;
10179     redund->isrow              = isrow;
10180     redund->iscol              = iscol;
10181     redund->matseq             = matseq;
10182     if (newsubcomm) {
10183       redund->subcomm = subcomm;
10184     } else {
10185       redund->subcomm = MPI_COMM_NULL;
10186     }
10187   } else {
10188     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10189   }
10190 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10191   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10192     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10193     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10194   }
10195 #endif
10196   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10197   PetscFunctionReturn(0);
10198 }
10199 
10200 /*@C
10201    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10202    a given `Mat`. Each submatrix can span multiple procs.
10203 
10204    Collective
10205 
10206    Input Parameters:
10207 +  mat - the matrix
10208 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
10209 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10210 
10211    Output Parameter:
10212 .  subMat - 'parallel submatrices each spans a given subcomm
10213 
10214   Notes:
10215   The submatrix partition across processors is dictated by 'subComm' a
10216   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
10217   is not restriced to be grouped with consecutive original ranks.
10218 
10219   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10220   map directly to the layout of the original matrix [wrt the local
10221   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10222   into the 'DiagonalMat' of the subMat, hence it is used directly from
10223   the subMat. However the offDiagMat looses some columns - and this is
10224   reconstructed with `MatSetValues()`
10225 
10226   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10227 
10228   Level: advanced
10229 
10230 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10231 @*/
10232 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10233 {
10234   PetscMPIInt commsize, subCommSize;
10235 
10236   PetscFunctionBegin;
10237   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10238   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10239   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10240 
10241   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");
10242   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10243   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10244   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10245   PetscFunctionReturn(0);
10246 }
10247 
10248 /*@
10249    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10250 
10251    Not Collective
10252 
10253    Input Parameters:
10254 +  mat - matrix to extract local submatrix from
10255 .  isrow - local row indices for submatrix
10256 -  iscol - local column indices for submatrix
10257 
10258    Output Parameter:
10259 .  submat - the submatrix
10260 
10261    Level: intermediate
10262 
10263    Notes:
10264    The submat should be returned with `MatRestoreLocalSubMatrix()`.
10265 
10266    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10267    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10268 
10269    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10270    `MatSetValuesBlockedLocal()` will also be implemented.
10271 
10272    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10273    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10274 
10275 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10276 @*/
10277 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10278 {
10279   PetscFunctionBegin;
10280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10281   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10282   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10283   PetscCheckSameComm(isrow, 2, iscol, 3);
10284   PetscValidPointer(submat, 4);
10285   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10286 
10287   if (mat->ops->getlocalsubmatrix) {
10288     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10289   } else {
10290     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10291   }
10292   PetscFunctionReturn(0);
10293 }
10294 
10295 /*@
10296    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10297 
10298    Not Collective
10299 
10300    Input Parameters:
10301 +  mat - matrix to extract local submatrix from
10302 .  isrow - local row indices for submatrix
10303 .  iscol - local column indices for submatrix
10304 -  submat - the submatrix
10305 
10306    Level: intermediate
10307 
10308 .seealso: `MatGetLocalSubMatrix()`
10309 @*/
10310 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10311 {
10312   PetscFunctionBegin;
10313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10314   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10315   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10316   PetscCheckSameComm(isrow, 2, iscol, 3);
10317   PetscValidPointer(submat, 4);
10318   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10319 
10320   if (mat->ops->restorelocalsubmatrix) {
10321     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10322   } else {
10323     PetscCall(MatDestroy(submat));
10324   }
10325   *submat = NULL;
10326   PetscFunctionReturn(0);
10327 }
10328 
10329 /* --------------------------------------------------------*/
10330 /*@
10331    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10332 
10333    Collective
10334 
10335    Input Parameter:
10336 .  mat - the matrix
10337 
10338    Output Parameter:
10339 .  is - if any rows have zero diagonals this contains the list of them
10340 
10341    Level: developer
10342 
10343 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10344 @*/
10345 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10346 {
10347   PetscFunctionBegin;
10348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10349   PetscValidType(mat, 1);
10350   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10351   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10352 
10353   if (!mat->ops->findzerodiagonals) {
10354     Vec                diag;
10355     const PetscScalar *a;
10356     PetscInt          *rows;
10357     PetscInt           rStart, rEnd, r, nrow = 0;
10358 
10359     PetscCall(MatCreateVecs(mat, &diag, NULL));
10360     PetscCall(MatGetDiagonal(mat, diag));
10361     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10362     PetscCall(VecGetArrayRead(diag, &a));
10363     for (r = 0; r < rEnd - rStart; ++r)
10364       if (a[r] == 0.0) ++nrow;
10365     PetscCall(PetscMalloc1(nrow, &rows));
10366     nrow = 0;
10367     for (r = 0; r < rEnd - rStart; ++r)
10368       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10369     PetscCall(VecRestoreArrayRead(diag, &a));
10370     PetscCall(VecDestroy(&diag));
10371     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10372   } else {
10373     PetscUseTypeMethod(mat, findzerodiagonals, is);
10374   }
10375   PetscFunctionReturn(0);
10376 }
10377 
10378 /*@
10379    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10380 
10381    Collective
10382 
10383    Input Parameter:
10384 .  mat - the matrix
10385 
10386    Output Parameter:
10387 .  is - contains the list of rows with off block diagonal entries
10388 
10389    Level: developer
10390 
10391 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10392 @*/
10393 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10394 {
10395   PetscFunctionBegin;
10396   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10397   PetscValidType(mat, 1);
10398   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10399   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10400 
10401   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10402   PetscFunctionReturn(0);
10403 }
10404 
10405 /*@C
10406   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10407 
10408   Collective; No Fortran Support
10409 
10410   Input Parameters:
10411 . mat - the matrix
10412 
10413   Output Parameters:
10414 . values - the block inverses in column major order (FORTRAN-like)
10415 
10416   Level: advanced
10417 
10418    Notes:
10419    The size of the blocks is determined by the block size of the matrix.
10420 
10421    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10422 
10423    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10424 
10425 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10426 @*/
10427 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10428 {
10429   PetscFunctionBegin;
10430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10431   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10432   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10433   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10434   PetscFunctionReturn(0);
10435 }
10436 
10437 /*@C
10438   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10439 
10440   Collective; No Fortran Support
10441 
10442   Input Parameters:
10443 + mat - the matrix
10444 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10445 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10446 
10447   Output Parameters:
10448 . values - the block inverses in column major order (FORTRAN-like)
10449 
10450   Level: advanced
10451 
10452   Notes:
10453   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10454 
10455   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10456 
10457 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10458 @*/
10459 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10460 {
10461   PetscFunctionBegin;
10462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10463   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10464   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10465   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10466   PetscFunctionReturn(0);
10467 }
10468 
10469 /*@
10470   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10471 
10472   Collective on Mat
10473 
10474   Input Parameters:
10475 + A - the matrix
10476 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10477 
10478   Note:
10479   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10480 
10481   Level: advanced
10482 
10483 .seealso: `MatInvertBlockDiagonal()`
10484 @*/
10485 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10486 {
10487   const PetscScalar *vals;
10488   PetscInt          *dnnz;
10489   PetscInt           m, rstart, rend, bs, i, j;
10490 
10491   PetscFunctionBegin;
10492   PetscCall(MatInvertBlockDiagonal(A, &vals));
10493   PetscCall(MatGetBlockSize(A, &bs));
10494   PetscCall(MatGetLocalSize(A, &m, NULL));
10495   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10496   PetscCall(PetscMalloc1(m / bs, &dnnz));
10497   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10498   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10499   PetscCall(PetscFree(dnnz));
10500   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10501   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10502   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10503   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10504   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10505   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10506   PetscFunctionReturn(0);
10507 }
10508 
10509 /*@C
10510     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10511     via `MatTransposeColoringCreate()`.
10512 
10513     Collective on c
10514 
10515     Input Parameter:
10516 .   c - coloring context
10517 
10518     Level: intermediate
10519 
10520 .seealso: `MatTransposeColoringCreate()`
10521 @*/
10522 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10523 {
10524   MatTransposeColoring matcolor = *c;
10525 
10526   PetscFunctionBegin;
10527   if (!matcolor) PetscFunctionReturn(0);
10528   if (--((PetscObject)matcolor)->refct > 0) {
10529     matcolor = NULL;
10530     PetscFunctionReturn(0);
10531   }
10532 
10533   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10534   PetscCall(PetscFree(matcolor->rows));
10535   PetscCall(PetscFree(matcolor->den2sp));
10536   PetscCall(PetscFree(matcolor->colorforcol));
10537   PetscCall(PetscFree(matcolor->columns));
10538   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10539   PetscCall(PetscHeaderDestroy(c));
10540   PetscFunctionReturn(0);
10541 }
10542 
10543 /*@C
10544     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10545     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10546     `MatTransposeColoring` to sparse B.
10547 
10548     Collective on coloring
10549 
10550     Input Parameters:
10551 +   B - sparse matrix B
10552 .   Btdense - symbolic dense matrix B^T
10553 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10554 
10555     Output Parameter:
10556 .   Btdense - dense matrix B^T
10557 
10558     Level: developer
10559 
10560     Note:
10561     These are used internally for some implementations of `MatRARt()`
10562 
10563 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10564 
10565 @*/
10566 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10567 {
10568   PetscFunctionBegin;
10569   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10570   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10571   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10572 
10573   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10574   PetscFunctionReturn(0);
10575 }
10576 
10577 /*@C
10578     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10579     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10580     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10581     Csp from Cden.
10582 
10583     Collective
10584 
10585     Input Parameters:
10586 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10587 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10588 
10589     Output Parameter:
10590 .   Csp - sparse matrix
10591 
10592     Level: developer
10593 
10594     Note:
10595     These are used internally for some implementations of `MatRARt()`
10596 
10597 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10598 
10599 @*/
10600 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10601 {
10602   PetscFunctionBegin;
10603   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10604   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10605   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10606 
10607   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10608   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10609   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10610   PetscFunctionReturn(0);
10611 }
10612 
10613 /*@C
10614    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10615 
10616    Collective
10617 
10618    Input Parameters:
10619 +  mat - the matrix product C
10620 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10621 
10622     Output Parameter:
10623 .   color - the new coloring context
10624 
10625     Level: intermediate
10626 
10627 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10628           `MatTransColoringApplyDenToSp()`
10629 @*/
10630 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10631 {
10632   MatTransposeColoring c;
10633   MPI_Comm             comm;
10634 
10635   PetscFunctionBegin;
10636   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10637   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10638   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10639 
10640   c->ctype = iscoloring->ctype;
10641   if (mat->ops->transposecoloringcreate) {
10642     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10643   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10644 
10645   *color = c;
10646   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10647   PetscFunctionReturn(0);
10648 }
10649 
10650 /*@
10651       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10652         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10653         same, otherwise it will be larger
10654 
10655      Not Collective
10656 
10657   Input Parameter:
10658 .    A  - the matrix
10659 
10660   Output Parameter:
10661 .    state - the current state
10662 
10663   Notes:
10664     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10665          different matrices
10666 
10667     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10668 
10669     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10670 
10671   Level: intermediate
10672 
10673 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10674 @*/
10675 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10676 {
10677   PetscFunctionBegin;
10678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10679   *state = mat->nonzerostate;
10680   PetscFunctionReturn(0);
10681 }
10682 
10683 /*@
10684       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10685                  matrices from each processor
10686 
10687     Collective
10688 
10689    Input Parameters:
10690 +    comm - the communicators the parallel matrix will live on
10691 .    seqmat - the input sequential matrices
10692 .    n - number of local columns (or `PETSC_DECIDE`)
10693 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10694 
10695    Output Parameter:
10696 .    mpimat - the parallel matrix generated
10697 
10698     Level: developer
10699 
10700    Note:
10701     The number of columns of the matrix in EACH processor MUST be the same.
10702 
10703 .seealso: `Mat`
10704 @*/
10705 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10706 {
10707   PetscMPIInt size;
10708 
10709   PetscFunctionBegin;
10710   PetscCallMPI(MPI_Comm_size(comm, &size));
10711   if (size == 1) {
10712     if (reuse == MAT_INITIAL_MATRIX) {
10713       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10714     } else {
10715       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10716     }
10717     PetscFunctionReturn(0);
10718   }
10719 
10720   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");
10721 
10722   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10723   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10724   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10725   PetscFunctionReturn(0);
10726 }
10727 
10728 /*@
10729      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10730 
10731     Collective on A
10732 
10733    Input Parameters:
10734 +    A   - the matrix to create subdomains from
10735 -    N   - requested number of subdomains
10736 
10737    Output Parameters:
10738 +    n   - number of subdomains resulting on this rank
10739 -    iss - `IS` list with indices of subdomains on this rank
10740 
10741     Level: advanced
10742 
10743     Note:
10744     The number of subdomains must be smaller than the communicator size
10745 
10746 .seealso: `Mat`, `IS`
10747 @*/
10748 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10749 {
10750   MPI_Comm    comm, subcomm;
10751   PetscMPIInt size, rank, color;
10752   PetscInt    rstart, rend, k;
10753 
10754   PetscFunctionBegin;
10755   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10756   PetscCallMPI(MPI_Comm_size(comm, &size));
10757   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10758   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);
10759   *n    = 1;
10760   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10761   color = rank / k;
10762   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10763   PetscCall(PetscMalloc1(1, iss));
10764   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10765   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10766   PetscCallMPI(MPI_Comm_free(&subcomm));
10767   PetscFunctionReturn(0);
10768 }
10769 
10770 /*@
10771    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10772 
10773    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10774    If they are not the same, uses `MatMatMatMult()`.
10775 
10776    Once the coarse grid problem is constructed, correct for interpolation operators
10777    that are not of full rank, which can legitimately happen in the case of non-nested
10778    geometric multigrid.
10779 
10780    Input Parameters:
10781 +  restrct - restriction operator
10782 .  dA - fine grid matrix
10783 .  interpolate - interpolation operator
10784 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10785 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10786 
10787    Output Parameters:
10788 .  A - the Galerkin coarse matrix
10789 
10790    Options Database Key:
10791 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10792 
10793    Level: developer
10794 
10795 .seealso: `MatPtAP()`, `MatMatMatMult()`
10796 @*/
10797 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10798 {
10799   IS  zerorows;
10800   Vec diag;
10801 
10802   PetscFunctionBegin;
10803   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10804   /* Construct the coarse grid matrix */
10805   if (interpolate == restrct) {
10806     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10807   } else {
10808     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10809   }
10810 
10811   /* If the interpolation matrix is not of full rank, A will have zero rows.
10812      This can legitimately happen in the case of non-nested geometric multigrid.
10813      In that event, we set the rows of the matrix to the rows of the identity,
10814      ignoring the equations (as the RHS will also be zero). */
10815 
10816   PetscCall(MatFindZeroRows(*A, &zerorows));
10817 
10818   if (zerorows != NULL) { /* if there are any zero rows */
10819     PetscCall(MatCreateVecs(*A, &diag, NULL));
10820     PetscCall(MatGetDiagonal(*A, diag));
10821     PetscCall(VecISSet(diag, zerorows, 1.0));
10822     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10823     PetscCall(VecDestroy(&diag));
10824     PetscCall(ISDestroy(&zerorows));
10825   }
10826   PetscFunctionReturn(0);
10827 }
10828 
10829 /*@C
10830     MatSetOperation - Allows user to set a matrix operation for any matrix type
10831 
10832    Logically Collective
10833 
10834     Input Parameters:
10835 +   mat - the matrix
10836 .   op - the name of the operation
10837 -   f - the function that provides the operation
10838 
10839    Level: developer
10840 
10841     Usage:
10842 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10843 $      PetscCall(MatCreateXXX(comm,...&A);
10844 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10845 
10846     Notes:
10847     See the file include/petscmat.h for a complete list of matrix
10848     operations, which all have the form MATOP_<OPERATION>, where
10849     <OPERATION> is the name (in all capital letters) of the
10850     user interface routine (e.g., MatMult() -> MATOP_MULT).
10851 
10852     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10853     sequence as the usual matrix interface routines, since they
10854     are intended to be accessed via the usual matrix interface
10855     routines, e.g.,
10856 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10857 
10858     In particular each function MUST return an error code of 0 on success and
10859     nonzero on failure.
10860 
10861     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10862 
10863 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10864 @*/
10865 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10866 {
10867   PetscFunctionBegin;
10868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10869   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10870   (((void (**)(void))mat->ops)[op]) = f;
10871   PetscFunctionReturn(0);
10872 }
10873 
10874 /*@C
10875     MatGetOperation - Gets a matrix operation for any matrix type.
10876 
10877     Not Collective
10878 
10879     Input Parameters:
10880 +   mat - the matrix
10881 -   op - the name of the operation
10882 
10883     Output Parameter:
10884 .   f - the function that provides the operation
10885 
10886     Level: developer
10887 
10888     Usage:
10889 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10890 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10891 
10892     Notes:
10893     See the file include/petscmat.h for a complete list of matrix
10894     operations, which all have the form MATOP_<OPERATION>, where
10895     <OPERATION> is the name (in all capital letters) of the
10896     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10897 
10898     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10899 
10900 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10901 @*/
10902 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10903 {
10904   PetscFunctionBegin;
10905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10906   *f = (((void (**)(void))mat->ops)[op]);
10907   PetscFunctionReturn(0);
10908 }
10909 
10910 /*@
10911     MatHasOperation - Determines whether the given matrix supports the particular operation.
10912 
10913    Not Collective
10914 
10915    Input Parameters:
10916 +  mat - the matrix
10917 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10918 
10919    Output Parameter:
10920 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10921 
10922    Level: advanced
10923 
10924    Note:
10925    See the file include/petscmat.h for a complete list of matrix
10926    operations, which all have the form MATOP_<OPERATION>, where
10927    <OPERATION> is the name (in all capital letters) of the
10928    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10929 
10930 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10931 @*/
10932 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10933 {
10934   PetscFunctionBegin;
10935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10936   PetscValidBoolPointer(has, 3);
10937   if (mat->ops->hasoperation) {
10938     PetscUseTypeMethod(mat, hasoperation, op, has);
10939   } else {
10940     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10941     else {
10942       *has = PETSC_FALSE;
10943       if (op == MATOP_CREATE_SUBMATRIX) {
10944         PetscMPIInt size;
10945 
10946         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10947         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10948       }
10949     }
10950   }
10951   PetscFunctionReturn(0);
10952 }
10953 
10954 /*@
10955     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10956 
10957    Collective
10958 
10959    Input Parameters:
10960 .  mat - the matrix
10961 
10962    Output Parameter:
10963 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10964 
10965    Level: beginner
10966 
10967 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10968 @*/
10969 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10970 {
10971   PetscFunctionBegin;
10972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10973   PetscValidType(mat, 1);
10974   PetscValidBoolPointer(cong, 2);
10975   if (!mat->rmap || !mat->cmap) {
10976     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10977     PetscFunctionReturn(0);
10978   }
10979   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10980     PetscCall(PetscLayoutSetUp(mat->rmap));
10981     PetscCall(PetscLayoutSetUp(mat->cmap));
10982     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10983     if (*cong) mat->congruentlayouts = 1;
10984     else mat->congruentlayouts = 0;
10985   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10986   PetscFunctionReturn(0);
10987 }
10988 
10989 PetscErrorCode MatSetInf(Mat A)
10990 {
10991   PetscFunctionBegin;
10992   PetscUseTypeMethod(A, setinf);
10993   PetscFunctionReturn(0);
10994 }
10995 
10996 /*C
10997    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
10998    and possibly removes small values from the graph structure.
10999 
11000    Collective
11001 
11002    Input Parameters:
11003 +  A - the matrix
11004 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11005 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11006 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11007 
11008    Output Parameter:
11009 .  graph - the resulting graph
11010 
11011    Level: advanced
11012 
11013 .seealso: `MatCreate()`, `PCGAMG`
11014 */
11015 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11016 {
11017   PetscFunctionBegin;
11018   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11019   PetscValidType(A, 1);
11020   PetscValidPointer(graph, 3);
11021   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11022   PetscFunctionReturn(0);
11023 }
11024