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