xref: /petsc/src/mat/interface/matrix.c (revision b9e5a4c7d30bdcab0a753290c79ea6b79adb512b)
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.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Output Parameter:
61 .  x  - the matrix
62 
63    Example of Usage:
64 .vb
65      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
66      MatSetRandom(x,rctx);
67      PetscRandomDestroy(rctx);
68 .ve
69 
70    Level: intermediate
71 
72    Note:
73    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
74    for sparse matrices that already have locations it fills the locations with random numbers. It generates an error if used on sparse matrices that have
75    not been preallocated.
76 
77 .seealso: `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(0);
105 }
106 
107 /*@
108    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109 
110    Logically Collective
111 
112    Input Parameter:
113 .  mat - the factored matrix
114 
115    Output Parameters:
116 +  pivot - the pivot value computed
117 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
118          the share the matrix
119 
120    Level: advanced
121 
122    Notes:
123     This routine does not work for factorizations done with external packages.
124 
125     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126 
127     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
128 
129 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
130           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscValidRealPointer(pivot, 2);
137   PetscValidIntPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(0);
141 }
142 
143 /*@
144    MatFactorGetError - gets the error code from a factorization
145 
146    Logically Collective
147 
148    Input Parameters:
149 .  mat - the factored matrix
150 
151    Output Parameter:
152 .  err  - the error code
153 
154    Level: advanced
155 
156    Note:
157     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
160           `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscValidPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(0);
169 }
170 
171 /*@
172    MatFactorClearError - clears the error code in a factorization
173 
174    Logically Collective
175 
176    Input Parameter:
177 .  mat - the factored matrix
178 
179    Level: developer
180 
181    Note:
182     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(0);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(0);
250 }
251 
252 /*@
253       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 .    A  - the matrix
257 
258   Output Parameter:
259 .    keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264     `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscValidPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(0);
279 }
280 
281 /*@
282       MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 .    A  - the matrix
286 
287   Output Parameter:
288 .    zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293     `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscValidPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(0);
318 }
319 
320 /*@
321    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323    Not Collective
324 
325    Input Parameters:
326 .   A - the matrix
327 
328    Output Parameters:
329 .   a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331    Level: advanced
332 
333    Notes:
334    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscValidPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(0);
356 }
357 
358 /*@
359    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361    Collective
362 
363    Input Parameters:
364 .  mat - the matrix
365 
366    Output Parameter:
367 .   trace - the sum of the diagonal entries
368 
369    Level: advanced
370 
371 .seealso: `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscValidScalarPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(0);
385 }
386 
387 /*@
388    MatRealPart - Zeros out the imaginary part of the matrix
389 
390    Logically Collective
391 
392    Input Parameters:
393 .  mat - the matrix
394 
395    Level: advanced
396 
397 .seealso: `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(0);
409 }
410 
411 /*@C
412    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414    Collective
415 
416    Input Parameter:
417 .  mat - the matrix
418 
419    Output Parameters:
420 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
421 -   ghosts - the global indices of the ghost points
422 
423    Level: advanced
424 
425    Note:
426    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
427 
428 .seealso: `Mat`, `VecCreateGhost()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(0);
443 }
444 
445 /*@
446    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448    Logically Collective
449 
450    Input Parameters:
451 .  mat - the matrix
452 
453    Level: advanced
454 
455 .seealso: `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(0);
467 }
468 
469 /*@
470    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
471 
472    Not Collective
473 
474    Input Parameter:
475 .  mat - the matrix
476 
477    Output Parameters:
478 +  missing - is any diagonal missing
479 -  dd - first diagonal entry that is missing (optional) on this process
480 
481    Level: advanced
482 
483 .seealso: `Mat`
484 @*/
485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
489   PetscValidType(mat, 1);
490   PetscValidBoolPointer(missing, 2);
491   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
492   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
493   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
494   PetscFunctionReturn(0);
495 }
496 
497 /*@C
498    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
499    for each row that you get to ensure that your application does
500    not bleed memory.
501 
502    Not Collective
503 
504    Input Parameters:
505 +  mat - the matrix
506 -  row - the row to get
507 
508    Output Parameters:
509 +  ncols -  if not `NULL`, the number of nonzeros in the row
510 .  cols - if not `NULL`, the column numbers
511 -  vals - if not `NULL`, the values
512 
513    Level: advanced
514 
515    Notes:
516    This routine is provided for people who need to have direct access
517    to the structure of a matrix.  We hope that we provide enough
518    high-level matrix routines that few users will need it.
519 
520    `MatGetRow()` always returns 0-based column indices, regardless of
521    whether the internal representation is 0-based (default) or 1-based.
522 
523    For better efficiency, set cols and/or vals to `NULL` if you do
524    not wish to extract these quantities.
525 
526    The user can only examine the values extracted with `MatGetRow()`;
527    the values cannot be altered.  To change the matrix entries, one
528    must use `MatSetValues()`.
529 
530    You can only have one call to `MatGetRow()` outstanding for a particular
531    matrix at a time, per processor. `MatGetRow()` can only obtain rows
532    associated with the given processor, it cannot get rows from the
533    other processors; for that we suggest using `MatCreateSubMatrices()`, then
534    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
535    is in the global number of rows.
536 
537    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
538 
539    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
540 
541    Fortran Note:
542    The calling sequence is
543 .vb
544    MatGetRow(matrix,row,ncols,cols,values,ierr)
545          Mat     matrix (input)
546          integer row    (input)
547          integer ncols  (output)
548          integer cols(maxcols) (output)
549          double precision (or double complex) values(maxcols) output
550 .ve
551    where maxcols >= maximum nonzeros in any row of the matrix.
552 
553    Caution:
554    Do not try to change the contents of the output arrays (cols and vals).
555    In some cases, this may corrupt the matrix.
556 
557 .seealso: `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   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);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(0);
575 }
576 
577 /*@
578    MatConjugate - replaces the matrix values with their complex conjugates
579 
580    Logically Collective
581 
582    Input Parameters:
583 .  mat - the matrix
584 
585    Level: advanced
586 
587 .seealso: `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(0);
599 }
600 
601 /*@C
602    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604    Not Collective
605 
606    Input Parameters:
607 +  mat - the matrix
608 .  row - the row to get
609 .  ncols, cols - the number of nonzeros and their columns
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(0);
645   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(0);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameters:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    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.
665 
666 .seealso: `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(0);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameters:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(0);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(0);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(0);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   char  *buf = A->factorprefix;
801   size_t len1, len2;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(0);
806   if (!buf) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(0);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(prefix, &len1));
813   PetscCall(PetscStrlen(buf, &len2));
814   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
815   PetscCall(PetscStrcpy(A->factorprefix, buf));
816   PetscCall(PetscStrcat(A->factorprefix, prefix));
817   PetscCall(PetscFree(buf));
818   PetscFunctionReturn(0);
819 }
820 
821 /*@C
822    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
823    matrix options in the database.
824 
825    Logically Collective
826 
827    Input Parameters:
828 +  A - the matrix
829 -  prefix - the prefix to prepend to all option names
830 
831    Level: advanced
832 
833    Note:
834    A hyphen (-) must NOT be given at the beginning of the prefix name.
835    The first character of all runtime options is AUTOMATICALLY the hyphen.
836 
837 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
838 @*/
839 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
840 {
841   PetscFunctionBegin;
842   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
843   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
844   PetscFunctionReturn(0);
845 }
846 
847 /*@C
848    MatGetOptionsPrefix - Gets the prefix used for searching for all
849    matrix options in the database.
850 
851    Not Collective
852 
853    Input Parameter:
854 .  A - the matrix
855 
856    Output Parameter:
857 .  prefix - pointer to the prefix string used
858 
859    Level: advanced
860 
861    Fortran Note:
862     On the fortran side, the user should pass in a string `prefix` of
863    sufficient length to hold the prefix.
864 
865 .seealso: `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
866 @*/
867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
868 {
869   PetscFunctionBegin;
870   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
871   PetscValidPointer(prefix, 2);
872   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
873   PetscFunctionReturn(0);
874 }
875 
876 /*@
877    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
878 
879    Collective
880 
881    Input Parameters:
882 .  A - the matrix
883 
884    Level: beginner
885 
886    Notes:
887    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
888 
889    Users can reset the preallocation to access the original memory.
890 
891    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
892 
893 .seealso: `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
894 @*/
895 PetscErrorCode MatResetPreallocation(Mat A)
896 {
897   PetscFunctionBegin;
898   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
899   PetscValidType(A, 1);
900   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
901   PetscFunctionReturn(0);
902 }
903 
904 /*@
905    MatSetUp - Sets up the internal matrix data structures for later use.
906 
907    Collective
908 
909    Input Parameters:
910 .  A - the matrix
911 
912    Level: intermediate
913 
914    Notes:
915    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
916 
917    If a suitable preallocation routine is used, this function does not need to be called.
918 
919    See the Performance chapter of the PETSc users manual for how to preallocate matrices
920 
921    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated && A->ops->setup) {
936     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
937     PetscUseTypeMethod(A, setup);
938   }
939   PetscCall(PetscLayoutSetUp(A->rmap));
940   PetscCall(PetscLayoutSetUp(A->cmap));
941   A->preallocated = PETSC_TRUE;
942   PetscFunctionReturn(0);
943 }
944 
945 #if defined(PETSC_HAVE_SAWS)
946   #include <petscviewersaws.h>
947 #endif
948 
949 /*@C
950    MatViewFromOptions - View properties of the matrix from the options database
951 
952    Collective
953 
954    Input Parameters:
955 +  A - the matrix
956 .  obj - optional additional object that provides the options prefix to use
957 -  name - command line option
958 
959   Options Database Key:
960 .  -mat_view [viewertype]:... - the viewer and its options
961 
962    Level: intermediate
963 
964   Notes:
965 .vb
966     If no value is provided ascii:stdout is used
967        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
968                                                   for example ascii::ascii_info prints just the information about the object not all details
969                                                   unless :append is given filename opens in write mode, overwriting what was already there
970        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
971        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
972        socket[:port]                             defaults to the standard output port
973        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
974 .ve
975 
976 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
977 @*/
978 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
979 {
980   PetscFunctionBegin;
981   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
982   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
983   PetscFunctionReturn(0);
984 }
985 
986 /*@C
987    MatView - display information about a matrix in a variety ways
988 
989    Collective
990 
991    Input Parameters:
992 +  mat - the matrix
993 -  viewer - visualization context
994 
995   Notes:
996   The available visualization contexts include
997 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
998 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
999 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1000 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1001 
1002    The user can open alternative visualization contexts with
1003 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1004 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1005          specified file; corresponding input uses MatLoad()
1006 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1007          an X window display
1008 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1009          Currently only the sequential dense and AIJ
1010          matrix types support the Socket viewer.
1011 
1012    The user can call `PetscViewerPushFormat()` to specify the output
1013    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1014    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1015 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1016 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1017 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1018 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1019          format common among all matrix types
1020 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1021          format (which is in many cases the same as the default)
1022 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1023          size and structure (not the matrix entries)
1024 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1025          the matrix structure
1026 
1027    Options Database Keys:
1028 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1029 .  -mat_view ::ascii_info_detail - Prints more detailed info
1030 .  -mat_view - Prints matrix in ASCII format
1031 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1032 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1033 .  -display <name> - Sets display name (default is host)
1034 .  -draw_pause <sec> - Sets number of seconds to pause after display
1035 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1036 .  -viewer_socket_machine <machine> -
1037 .  -viewer_socket_port <port> -
1038 .  -mat_view binary - save matrix to file in binary format
1039 -  -viewer_binary_filename <name> -
1040 
1041    Level: beginner
1042 
1043    Notes:
1044     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1045     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1046 
1047     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1048 
1049     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1050       viewer is used.
1051 
1052       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1053       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1054 
1055       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1056       and then use the following mouse functions.
1057 .vb
1058   left mouse: zoom in
1059   middle mouse: zoom out
1060   right mouse: continue with the simulation
1061 .ve
1062 
1063 .seealso: `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1064           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1065 @*/
1066 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1067 {
1068   PetscInt          rows, cols, rbs, cbs;
1069   PetscBool         isascii, isstring, issaws;
1070   PetscViewerFormat format;
1071   PetscMPIInt       size;
1072 
1073   PetscFunctionBegin;
1074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1075   PetscValidType(mat, 1);
1076   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1077   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1078   PetscCheckSameComm(mat, 1, viewer, 2);
1079 
1080   PetscCall(PetscViewerGetFormat(viewer, &format));
1081   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1082   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1083 
1084   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1085   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1086   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1087   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");
1088 
1089   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1090   if (isascii) {
1091     if (!mat->preallocated) {
1092       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1093       PetscFunctionReturn(0);
1094     }
1095     if (!mat->assembled) {
1096       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1097       PetscFunctionReturn(0);
1098     }
1099     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1100     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1101       MatNullSpace nullsp, transnullsp;
1102 
1103       PetscCall(PetscViewerASCIIPushTab(viewer));
1104       PetscCall(MatGetSize(mat, &rows, &cols));
1105       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1106       if (rbs != 1 || cbs != 1) {
1107         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1108         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1109       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1110       if (mat->factortype) {
1111         MatSolverType solver;
1112         PetscCall(MatFactorGetSolverType(mat, &solver));
1113         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1114       }
1115       if (mat->ops->getinfo) {
1116         MatInfo info;
1117         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1118         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1119         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1120       }
1121       PetscCall(MatGetNullSpace(mat, &nullsp));
1122       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1123       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1124       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1125       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1126       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1127       PetscCall(PetscViewerASCIIPushTab(viewer));
1128       PetscCall(MatProductView(mat, viewer));
1129       PetscCall(PetscViewerASCIIPopTab(viewer));
1130     }
1131   } else if (issaws) {
1132 #if defined(PETSC_HAVE_SAWS)
1133     PetscMPIInt rank;
1134 
1135     PetscCall(PetscObjectName((PetscObject)mat));
1136     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1137     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1138 #endif
1139   } else if (isstring) {
1140     const char *type;
1141     PetscCall(MatGetType(mat, &type));
1142     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1143     PetscTryTypeMethod(mat, view, viewer);
1144   }
1145   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1146     PetscCall(PetscViewerASCIIPushTab(viewer));
1147     PetscUseTypeMethod(mat, viewnative, viewer);
1148     PetscCall(PetscViewerASCIIPopTab(viewer));
1149   } else if (mat->ops->view) {
1150     PetscCall(PetscViewerASCIIPushTab(viewer));
1151     PetscUseTypeMethod(mat, view, viewer);
1152     PetscCall(PetscViewerASCIIPopTab(viewer));
1153   }
1154   if (isascii) {
1155     PetscCall(PetscViewerGetFormat(viewer, &format));
1156     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1157   }
1158   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1159   PetscFunctionReturn(0);
1160 }
1161 
1162 #if defined(PETSC_USE_DEBUG)
1163   #include <../src/sys/totalview/tv_data_display.h>
1164 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1165 {
1166   TV_add_row("Local rows", "int", &mat->rmap->n);
1167   TV_add_row("Local columns", "int", &mat->cmap->n);
1168   TV_add_row("Global rows", "int", &mat->rmap->N);
1169   TV_add_row("Global columns", "int", &mat->cmap->N);
1170   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1171   return TV_format_OK;
1172 }
1173 #endif
1174 
1175 /*@C
1176    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1177    with `MatView()`.  The matrix format is determined from the options database.
1178    Generates a parallel MPI matrix if the communicator has more than one
1179    processor.  The default matrix type is `MATAIJ`.
1180 
1181    Collective
1182 
1183    Input Parameters:
1184 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1185             or some related function before a call to `MatLoad()`
1186 -  viewer - binary/HDF5 file viewer
1187 
1188    Options Database Keys:
1189    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1190    block size
1191 .    -matload_block_size <bs> - set block size
1192 
1193    Level: beginner
1194 
1195    Notes:
1196    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1197    `Mat` before calling this routine if you wish to set it from the options database.
1198 
1199    `MatLoad()` automatically loads into the options database any options
1200    given in the file filename.info where filename is the name of the file
1201    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1202    file will be ignored if you use the -viewer_binary_skip_info option.
1203 
1204    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1205    sets the default matrix type AIJ and sets the local and global sizes.
1206    If type and/or size is already set, then the same are used.
1207 
1208    In parallel, each processor can load a subset of rows (or the
1209    entire matrix).  This routine is especially useful when a large
1210    matrix is stored on disk and only part of it is desired on each
1211    processor.  For example, a parallel solver may access only some of
1212    the rows from each processor.  The algorithm used here reads
1213    relatively small blocks of data rather than reading the entire
1214    matrix and then subsetting it.
1215 
1216    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1217    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1218    or the sequence like
1219 .vb
1220     `PetscViewer` v;
1221     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1222     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1223     `PetscViewerSetFromOptions`(v);
1224     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1225     `PetscViewerFileSetName`(v,"datafile");
1226 .ve
1227    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1228 $ -viewer_type {binary,hdf5}
1229 
1230    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1231    and src/mat/tutorials/ex10.c with the second approach.
1232 
1233    Notes about the PETSc binary format:
1234    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1235    is read onto rank 0 and then shipped to its destination rank, one after another.
1236    Multiple objects, both matrices and vectors, can be stored within the same file.
1237    Their PetscObject name is ignored; they are loaded in the order of their storage.
1238 
1239    Most users should not need to know the details of the binary storage
1240    format, since `MatLoad()` and `MatView()` completely hide these details.
1241    But for anyone who's interested, the standard binary matrix storage
1242    format is
1243 
1244 $    PetscInt    MAT_FILE_CLASSID
1245 $    PetscInt    number of rows
1246 $    PetscInt    number of columns
1247 $    PetscInt    total number of nonzeros
1248 $    PetscInt    *number nonzeros in each row
1249 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1250 $    PetscScalar *values of all nonzeros
1251 
1252    PETSc automatically does the byte swapping for
1253 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1254 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1255 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1256 and `PetscBinaryWrite()` to see how this may be done.
1257 
1258    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1259    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1260    Each processor's chunk is loaded independently by its owning rank.
1261    Multiple objects, both matrices and vectors, can be stored within the same file.
1262    They are looked up by their PetscObject name.
1263 
1264    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1265    by default the same structure and naming of the AIJ arrays and column count
1266    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1267 $    save example.mat A b -v7.3
1268    can be directly read by this routine (see Reference 1 for details).
1269    Note that depending on your MATLAB version, this format might be a default,
1270    otherwise you can set it as default in Preferences.
1271 
1272    Unless -nocompression flag is used to save the file in MATLAB,
1273    PETSc must be configured with ZLIB package.
1274 
1275    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1276 
1277    Current HDF5 (MAT-File) limitations:
1278    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1279 
1280    Corresponding `MatView()` is not yet implemented.
1281 
1282    The loaded matrix is actually a transpose of the original one in MATLAB,
1283    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1284    With this format, matrix is automatically transposed by PETSc,
1285    unless the matrix is marked as SPD or symmetric
1286    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1287 
1288    References:
1289 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1290 
1291 .seealso: `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1292  @*/
1293 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1294 {
1295   PetscBool flg;
1296 
1297   PetscFunctionBegin;
1298   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1299   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1300 
1301   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1302 
1303   flg = PETSC_FALSE;
1304   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1305   if (flg) {
1306     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1307     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1308   }
1309   flg = PETSC_FALSE;
1310   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1311   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1312 
1313   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1314   PetscUseTypeMethod(mat, load, viewer);
1315   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1316   PetscFunctionReturn(0);
1317 }
1318 
1319 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1320 {
1321   Mat_Redundant *redund = *redundant;
1322 
1323   PetscFunctionBegin;
1324   if (redund) {
1325     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1326       PetscCall(ISDestroy(&redund->isrow));
1327       PetscCall(ISDestroy(&redund->iscol));
1328       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1329     } else {
1330       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1331       PetscCall(PetscFree(redund->sbuf_j));
1332       PetscCall(PetscFree(redund->sbuf_a));
1333       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1334         PetscCall(PetscFree(redund->rbuf_j[i]));
1335         PetscCall(PetscFree(redund->rbuf_a[i]));
1336       }
1337       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1338     }
1339 
1340     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1341     PetscCall(PetscFree(redund));
1342   }
1343   PetscFunctionReturn(0);
1344 }
1345 
1346 /*@C
1347    MatDestroy - Frees space taken by a matrix.
1348 
1349    Collective
1350 
1351    Input Parameter:
1352 .  A - the matrix
1353 
1354    Level: beginner
1355 
1356    Developer Note:
1357    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1358    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1359    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1360    if changes are needed here.
1361 
1362 .seealso: `Mat`, `MatCreate()`
1363 @*/
1364 PetscErrorCode MatDestroy(Mat *A)
1365 {
1366   PetscFunctionBegin;
1367   if (!*A) PetscFunctionReturn(0);
1368   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1369   if (--((PetscObject)(*A))->refct > 0) {
1370     *A = NULL;
1371     PetscFunctionReturn(0);
1372   }
1373 
1374   /* if memory was published with SAWs then destroy it */
1375   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1376   PetscTryTypeMethod((*A), destroy);
1377 
1378   PetscCall(PetscFree((*A)->factorprefix));
1379   PetscCall(PetscFree((*A)->defaultvectype));
1380   PetscCall(PetscFree((*A)->defaultrandtype));
1381   PetscCall(PetscFree((*A)->bsizes));
1382   PetscCall(PetscFree((*A)->solvertype));
1383   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1384   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1385   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1386   PetscCall(MatProductClear(*A));
1387   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1388   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1389   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1390   PetscCall(MatDestroy(&(*A)->schur));
1391   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1392   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1393   PetscCall(PetscHeaderDestroy(A));
1394   PetscFunctionReturn(0);
1395 }
1396 
1397 /*@C
1398    MatSetValues - Inserts or adds a block of values into a matrix.
1399    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1400    MUST be called after all calls to `MatSetValues()` have been completed.
1401 
1402    Not Collective
1403 
1404    Input Parameters:
1405 +  mat - the matrix
1406 .  v - a logically two-dimensional array of values
1407 .  m, idxm - the number of rows and their global indices
1408 .  n, idxn - the number of columns and their global indices
1409 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1410 
1411    Level: beginner
1412 
1413    Notes:
1414    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1415       `MatSetUp()` before using this routine
1416 
1417    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1418 
1419    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1420    options cannot be mixed without intervening calls to the assembly
1421    routines.
1422 
1423    `MatSetValues()` uses 0-based row and column numbers in Fortran
1424    as well as in C.
1425 
1426    Negative indices may be passed in idxm and idxn, these rows and columns are
1427    simply ignored. This allows easily inserting element stiffness matrices
1428    with homogeneous Dirchlet boundary conditions that you don't want represented
1429    in the matrix.
1430 
1431    Efficiency Alert:
1432    The routine `MatSetValuesBlocked()` may offer much better efficiency
1433    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1434 
1435    Developer Note:
1436    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1437    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1438 
1439 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1440           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1441 @*/
1442 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1443 {
1444   PetscFunctionBeginHot;
1445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1446   PetscValidType(mat, 1);
1447   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1448   PetscValidIntPointer(idxm, 3);
1449   PetscValidIntPointer(idxn, 5);
1450   MatCheckPreallocated(mat, 1);
1451 
1452   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1453   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1454 
1455   if (PetscDefined(USE_DEBUG)) {
1456     PetscInt i, j;
1457 
1458     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1459     for (i = 0; i < m; i++) {
1460       for (j = 0; j < n; j++) {
1461         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1462 #if defined(PETSC_USE_COMPLEX)
1463           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]);
1464 #else
1465           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]);
1466 #endif
1467       }
1468     }
1469     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);
1470     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);
1471   }
1472 
1473   if (mat->assembled) {
1474     mat->was_assembled = PETSC_TRUE;
1475     mat->assembled     = PETSC_FALSE;
1476   }
1477   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1478   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1479   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1480   PetscFunctionReturn(0);
1481 }
1482 
1483 /*@C
1484    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1485    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1486    MUST be called after all calls to `MatSetValues()` have been completed.
1487 
1488    Not Collective
1489 
1490    Input Parameters:
1491 +  mat - the matrix
1492 .  v - a logically two-dimensional array of values
1493 .  ism - the rows to provide
1494 .  isn - the columns to provide
1495 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1496 
1497    Level: beginner
1498 
1499    Notes:
1500    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1501       `MatSetUp()` before using this routine
1502 
1503    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1504 
1505    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1506    options cannot be mixed without intervening calls to the assembly
1507    routines.
1508 
1509    `MatSetValues()` uses 0-based row and column numbers in Fortran
1510    as well as in C.
1511 
1512    Negative indices may be passed in ism and isn, these rows and columns are
1513    simply ignored. This allows easily inserting element stiffness matrices
1514    with homogeneous Dirchlet boundary conditions that you don't want represented
1515    in the matrix.
1516 
1517    Efficiency Alert:
1518    The routine `MatSetValuesBlocked()` may offer much better efficiency
1519    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1520 
1521     This is currently not optimized for any particular `ISType`
1522 
1523    Developer Notes:
1524     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1525                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1526 
1527 .seealso: `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1528           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1529 @*/
1530 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1531 {
1532   PetscInt        m, n;
1533   const PetscInt *rows, *cols;
1534 
1535   PetscFunctionBeginHot;
1536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1537   PetscCall(ISGetIndices(ism, &rows));
1538   PetscCall(ISGetIndices(isn, &cols));
1539   PetscCall(ISGetLocalSize(ism, &m));
1540   PetscCall(ISGetLocalSize(isn, &n));
1541   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1542   PetscCall(ISRestoreIndices(ism, &rows));
1543   PetscCall(ISRestoreIndices(isn, &cols));
1544   PetscFunctionReturn(0);
1545 }
1546 
1547 /*@
1548    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1549         values into a matrix
1550 
1551    Not Collective
1552 
1553    Input Parameters:
1554 +  mat - the matrix
1555 .  row - the (block) row to set
1556 -  v - a logically two-dimensional array of values
1557 
1558    Level: intermediate
1559 
1560    Notes:
1561    The values, `v`, are column-oriented (for the block version) and sorted
1562 
1563    All the nonzeros in the row must be provided
1564 
1565    The matrix must have previously had its column indices set
1566 
1567    The row must belong to this process
1568 
1569 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1570           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1571 @*/
1572 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1573 {
1574   PetscInt globalrow;
1575 
1576   PetscFunctionBegin;
1577   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1578   PetscValidType(mat, 1);
1579   PetscValidScalarPointer(v, 3);
1580   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1581   PetscCall(MatSetValuesRow(mat, globalrow, v));
1582   PetscFunctionReturn(0);
1583 }
1584 
1585 /*@
1586    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1587         values into a matrix
1588 
1589    Not Collective
1590 
1591    Input Parameters:
1592 +  mat - the matrix
1593 .  row - the (block) row to set
1594 -  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
1595 
1596    Level: advanced
1597 
1598    Notes:
1599    The values, `v`, are column-oriented for the block version.
1600 
1601    All the nonzeros in the row must be provided
1602 
1603    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1604 
1605    The row must belong to this process
1606 
1607 .seealso: `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1608           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1609 @*/
1610 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1611 {
1612   PetscFunctionBeginHot;
1613   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1614   PetscValidType(mat, 1);
1615   MatCheckPreallocated(mat, 1);
1616   PetscValidScalarPointer(v, 3);
1617   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1618   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1619   mat->insertmode = INSERT_VALUES;
1620 
1621   if (mat->assembled) {
1622     mat->was_assembled = PETSC_TRUE;
1623     mat->assembled     = PETSC_FALSE;
1624   }
1625   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1626   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1627   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1628   PetscFunctionReturn(0);
1629 }
1630 
1631 /*@
1632    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1633      Using structured grid indexing
1634 
1635    Not Collective
1636 
1637    Input Parameters:
1638 +  mat - the matrix
1639 .  m - number of rows being entered
1640 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1641 .  n - number of columns being entered
1642 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1643 .  v - a logically two-dimensional array of values
1644 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1645 
1646    Level: beginner
1647 
1648    Notes:
1649    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1650 
1651    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1652    options cannot be mixed without intervening calls to the assembly
1653    routines.
1654 
1655    The grid coordinates are across the entire grid, not just the local portion
1656 
1657    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1658    as well as in C.
1659 
1660    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1661 
1662    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1663    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1664 
1665    The columns and rows in the stencil passed in MUST be contained within the
1666    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1667    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1668    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1669    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1670 
1671    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1672    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1673    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1674    `DM_BOUNDARY_PERIODIC` boundary type.
1675 
1676    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
1677    a single value per point) you can skip filling those indices.
1678 
1679    Inspired by the structured grid interface to the HYPRE package
1680    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1681 
1682    Efficiency Alert:
1683    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1684    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1685 
1686    Fortran Note:
1687    In Fortran idxm and idxn should be declared as
1688 $     MatStencil idxm(4,m),idxn(4,n)
1689    and the values inserted using
1690 .vb
1691     idxm(MatStencil_i,1) = i
1692     idxm(MatStencil_j,1) = j
1693     idxm(MatStencil_k,1) = k
1694     idxm(MatStencil_c,1) = c
1695     etc
1696 .ve
1697 
1698 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1699           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1700 @*/
1701 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1702 {
1703   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1704   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1705   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1706 
1707   PetscFunctionBegin;
1708   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1709   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1710   PetscValidType(mat, 1);
1711   PetscValidPointer(idxm, 3);
1712   PetscValidPointer(idxn, 5);
1713 
1714   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1715     jdxm = buf;
1716     jdxn = buf + m;
1717   } else {
1718     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1719     jdxm = bufm;
1720     jdxn = bufn;
1721   }
1722   for (i = 0; i < m; i++) {
1723     for (j = 0; j < 3 - sdim; j++) dxm++;
1724     tmp = *dxm++ - starts[0];
1725     for (j = 0; j < dim - 1; j++) {
1726       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1727       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1728     }
1729     if (mat->stencil.noc) dxm++;
1730     jdxm[i] = tmp;
1731   }
1732   for (i = 0; i < n; i++) {
1733     for (j = 0; j < 3 - sdim; j++) dxn++;
1734     tmp = *dxn++ - starts[0];
1735     for (j = 0; j < dim - 1; j++) {
1736       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1737       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1738     }
1739     if (mat->stencil.noc) dxn++;
1740     jdxn[i] = tmp;
1741   }
1742   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1743   PetscCall(PetscFree2(bufm, bufn));
1744   PetscFunctionReturn(0);
1745 }
1746 
1747 /*@
1748    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1749      Using structured grid indexing
1750 
1751    Not Collective
1752 
1753    Input Parameters:
1754 +  mat - the matrix
1755 .  m - number of rows being entered
1756 .  idxm - grid coordinates for matrix rows being entered
1757 .  n - number of columns being entered
1758 .  idxn - grid coordinates for matrix columns being entered
1759 .  v - a logically two-dimensional array of values
1760 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1761 
1762    Level: beginner
1763 
1764    Notes:
1765    By default the values, `v`, are row-oriented and unsorted.
1766    See `MatSetOption()` for other options.
1767 
1768    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1769    options cannot be mixed without intervening calls to the assembly
1770    routines.
1771 
1772    The grid coordinates are across the entire grid, not just the local portion
1773 
1774    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1775    as well as in C.
1776 
1777    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1778 
1779    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1780    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1781 
1782    The columns and rows in the stencil passed in MUST be contained within the
1783    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1784    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1785    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1786    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1787 
1788    Negative indices may be passed in idxm and idxn, these rows and columns are
1789    simply ignored. This allows easily inserting element stiffness matrices
1790    with homogeneous Dirchlet boundary conditions that you don't want represented
1791    in the matrix.
1792 
1793    Inspired by the structured grid interface to the HYPRE package
1794    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1795 
1796    Fortran Note:
1797    In Fortran idxm and idxn should be declared as
1798 $     MatStencil idxm(4,m),idxn(4,n)
1799    and the values inserted using
1800 .vb
1801     idxm(MatStencil_i,1) = i
1802     idxm(MatStencil_j,1) = j
1803     idxm(MatStencil_k,1) = k
1804    etc
1805 .ve
1806 
1807 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1808           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1809           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1810 @*/
1811 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1812 {
1813   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1814   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1815   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1816 
1817   PetscFunctionBegin;
1818   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1820   PetscValidType(mat, 1);
1821   PetscValidPointer(idxm, 3);
1822   PetscValidPointer(idxn, 5);
1823   PetscValidScalarPointer(v, 6);
1824 
1825   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1826     jdxm = buf;
1827     jdxn = buf + m;
1828   } else {
1829     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1830     jdxm = bufm;
1831     jdxn = bufn;
1832   }
1833   for (i = 0; i < m; i++) {
1834     for (j = 0; j < 3 - sdim; j++) dxm++;
1835     tmp = *dxm++ - starts[0];
1836     for (j = 0; j < sdim - 1; j++) {
1837       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1838       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1839     }
1840     dxm++;
1841     jdxm[i] = tmp;
1842   }
1843   for (i = 0; i < n; i++) {
1844     for (j = 0; j < 3 - sdim; j++) dxn++;
1845     tmp = *dxn++ - starts[0];
1846     for (j = 0; j < sdim - 1; j++) {
1847       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1848       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1849     }
1850     dxn++;
1851     jdxn[i] = tmp;
1852   }
1853   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1854   PetscCall(PetscFree2(bufm, bufn));
1855   PetscFunctionReturn(0);
1856 }
1857 
1858 /*@
1859    MatSetStencil - Sets the grid information for setting values into a matrix via
1860         `MatSetValuesStencil()`
1861 
1862    Not Collective
1863 
1864    Input Parameters:
1865 +  mat - the matrix
1866 .  dim - dimension of the grid 1, 2, or 3
1867 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1868 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1869 -  dof - number of degrees of freedom per node
1870 
1871    Level: beginner
1872 
1873    Notes:
1874    Inspired by the structured grid interface to the HYPRE package
1875    (www.llnl.gov/CASC/hyper)
1876 
1877    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1878    user.
1879 
1880 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1881           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1882 @*/
1883 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1884 {
1885   PetscFunctionBegin;
1886   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1887   PetscValidIntPointer(dims, 3);
1888   PetscValidIntPointer(starts, 4);
1889 
1890   mat->stencil.dim = dim + (dof > 1);
1891   for (PetscInt i = 0; i < dim; i++) {
1892     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1893     mat->stencil.starts[i] = starts[dim - i - 1];
1894   }
1895   mat->stencil.dims[dim]   = dof;
1896   mat->stencil.starts[dim] = 0;
1897   mat->stencil.noc         = (PetscBool)(dof == 1);
1898   PetscFunctionReturn(0);
1899 }
1900 
1901 /*@C
1902    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1903 
1904    Not Collective
1905 
1906    Input Parameters:
1907 +  mat - the matrix
1908 .  v - a logically two-dimensional array of values
1909 .  m  - the number of block rows
1910 .  idxm - the global block indices
1911 .  n - the number of block columns
1912 .  idxn - the global block indices
1913 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1914 
1915    Level: intermediate
1916 
1917    Notes:
1918    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1919    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1920 
1921    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1922    NOT the total number of rows/columns; for example, if the block size is 2 and
1923    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1924    The values in idxm would be 1 2; that is the first index for each block divided by
1925    the block size.
1926 
1927    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1928    preallocating it).
1929 
1930    By default the values, `v`, are row-oriented, so the layout of
1931    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1932 
1933    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1934    options cannot be mixed without intervening calls to the assembly
1935    routines.
1936 
1937    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1938    as well as in C.
1939 
1940    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1941    simply ignored. This allows easily inserting element stiffness matrices
1942    with homogeneous Dirchlet boundary conditions that you don't want represented
1943    in the matrix.
1944 
1945    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1946    internal searching must be done to determine where to place the
1947    data in the matrix storage space.  By instead inserting blocks of
1948    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1949    reduced.
1950 
1951    Example:
1952 .vb
1953    Suppose m=n=2 and block size(bs) = 2 The array is
1954 
1955    1  2  | 3  4
1956    5  6  | 7  8
1957    - - - | - - -
1958    9  10 | 11 12
1959    13 14 | 15 16
1960 
1961    v[] should be passed in like
1962    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1963 
1964   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1965    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1966 .ve
1967 
1968 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1969 @*/
1970 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1971 {
1972   PetscFunctionBeginHot;
1973   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1974   PetscValidType(mat, 1);
1975   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1976   PetscValidIntPointer(idxm, 3);
1977   PetscValidIntPointer(idxn, 5);
1978   MatCheckPreallocated(mat, 1);
1979   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1980   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1981   if (PetscDefined(USE_DEBUG)) {
1982     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1983     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1984   }
1985   if (PetscDefined(USE_DEBUG)) {
1986     PetscInt rbs, cbs, M, N, i;
1987     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1988     PetscCall(MatGetSize(mat, &M, &N));
1989     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);
1990     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);
1991   }
1992   if (mat->assembled) {
1993     mat->was_assembled = PETSC_TRUE;
1994     mat->assembled     = PETSC_FALSE;
1995   }
1996   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1997   if (mat->ops->setvaluesblocked) {
1998     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1999   } else {
2000     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2001     PetscInt i, j, bs, cbs;
2002 
2003     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2004     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2005       iidxm = buf;
2006       iidxn = buf + m * bs;
2007     } else {
2008       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2009       iidxm = bufr;
2010       iidxn = bufc;
2011     }
2012     for (i = 0; i < m; i++) {
2013       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2014     }
2015     if (m != n || bs != cbs || idxm != idxn) {
2016       for (i = 0; i < n; i++) {
2017         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2018       }
2019     } else iidxn = iidxm;
2020     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2021     PetscCall(PetscFree2(bufr, bufc));
2022   }
2023   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2024   PetscFunctionReturn(0);
2025 }
2026 
2027 /*@C
2028    MatGetValues - Gets a block of local values from a matrix.
2029 
2030    Not Collective; can only return values that are owned by the give process
2031 
2032    Input Parameters:
2033 +  mat - the matrix
2034 .  v - a logically two-dimensional array for storing the values
2035 .  m  - the number of rows
2036 .  idxm - the  global indices of the rows
2037 .  n - the number of columns
2038 -  idxn - the global indices of the columns
2039 
2040    Level: advanced
2041 
2042    Notes:
2043      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2044      The values, `v`, are then returned in a row-oriented format,
2045      analogous to that used by default in `MatSetValues()`.
2046 
2047      `MatGetValues()` uses 0-based row and column numbers in
2048      Fortran as well as in C.
2049 
2050      `MatGetValues()` requires that the matrix has been assembled
2051      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2052      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2053      without intermediate matrix assembly.
2054 
2055      Negative row or column indices will be ignored and those locations in `v` will be
2056      left unchanged.
2057 
2058      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2059      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2060      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2061 
2062 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2063 @*/
2064 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2065 {
2066   PetscFunctionBegin;
2067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2068   PetscValidType(mat, 1);
2069   if (!m || !n) PetscFunctionReturn(0);
2070   PetscValidIntPointer(idxm, 3);
2071   PetscValidIntPointer(idxn, 5);
2072   PetscValidScalarPointer(v, 6);
2073   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2074   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2075   MatCheckPreallocated(mat, 1);
2076 
2077   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2078   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2079   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2080   PetscFunctionReturn(0);
2081 }
2082 
2083 /*@C
2084    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2085      defined previously by `MatSetLocalToGlobalMapping()`
2086 
2087    Not Collective
2088 
2089    Input Parameters:
2090 +  mat - the matrix
2091 .  nrow - number of rows
2092 .  irow - the row local indices
2093 .  ncol - number of columns
2094 -  icol - the column local indices
2095 
2096    Output Parameter:
2097 .  y -  a logically two-dimensional array of values
2098 
2099    Level: advanced
2100 
2101    Notes:
2102      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2103 
2104      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,
2105      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2106      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2107      with `MatSetLocalToGlobalMapping()`.
2108 
2109    Developer Note:
2110       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2111       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2112 
2113 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2114           `MatSetValuesLocal()`, `MatGetValues()`
2115 @*/
2116 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2117 {
2118   PetscFunctionBeginHot;
2119   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2120   PetscValidType(mat, 1);
2121   MatCheckPreallocated(mat, 1);
2122   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2123   PetscValidIntPointer(irow, 3);
2124   PetscValidIntPointer(icol, 5);
2125   if (PetscDefined(USE_DEBUG)) {
2126     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2127     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2128   }
2129   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2130   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2131   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2132   else {
2133     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2134     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2135       irowm = buf;
2136       icolm = buf + nrow;
2137     } else {
2138       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2139       irowm = bufr;
2140       icolm = bufc;
2141     }
2142     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2143     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2144     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2145     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2146     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2147     PetscCall(PetscFree2(bufr, bufc));
2148   }
2149   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2150   PetscFunctionReturn(0);
2151 }
2152 
2153 /*@
2154   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2155   the same size. Currently, this can only be called once and creates the given matrix.
2156 
2157   Not Collective
2158 
2159   Input Parameters:
2160 + mat - the matrix
2161 . nb - the number of blocks
2162 . bs - the number of rows (and columns) in each block
2163 . rows - a concatenation of the rows for each block
2164 - v - a concatenation of logically two-dimensional arrays of values
2165 
2166   Level: advanced
2167 
2168   Note:
2169   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2170 
2171   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2172 
2173 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2174           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2175 @*/
2176 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2177 {
2178   PetscFunctionBegin;
2179   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2180   PetscValidType(mat, 1);
2181   PetscValidIntPointer(rows, 4);
2182   PetscValidScalarPointer(v, 5);
2183   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2184 
2185   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2186   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2187   else {
2188     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2189   }
2190   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2191   PetscFunctionReturn(0);
2192 }
2193 
2194 /*@
2195    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2196    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2197    using a local (per-processor) numbering.
2198 
2199    Not Collective
2200 
2201    Input Parameters:
2202 +  x - the matrix
2203 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2204 -  cmapping - column mapping
2205 
2206    Level: intermediate
2207 
2208    Note:
2209    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2210 
2211 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2212 @*/
2213 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2214 {
2215   PetscFunctionBegin;
2216   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2217   PetscValidType(x, 1);
2218   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2219   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2220   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2221   else {
2222     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2223     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2224   }
2225   PetscFunctionReturn(0);
2226 }
2227 
2228 /*@
2229    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2230 
2231    Not Collective
2232 
2233    Input Parameter:
2234 .  A - the matrix
2235 
2236    Output Parameters:
2237 + rmapping - row mapping
2238 - cmapping - column mapping
2239 
2240    Level: advanced
2241 
2242 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2243 @*/
2244 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2245 {
2246   PetscFunctionBegin;
2247   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2248   PetscValidType(A, 1);
2249   if (rmapping) {
2250     PetscValidPointer(rmapping, 2);
2251     *rmapping = A->rmap->mapping;
2252   }
2253   if (cmapping) {
2254     PetscValidPointer(cmapping, 3);
2255     *cmapping = A->cmap->mapping;
2256   }
2257   PetscFunctionReturn(0);
2258 }
2259 
2260 /*@
2261    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2262 
2263    Logically Collective
2264 
2265    Input Parameters:
2266 +  A - the matrix
2267 . rmap - row layout
2268 - cmap - column layout
2269 
2270    Level: advanced
2271 
2272    Note:
2273    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2274 
2275 .seealso: `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2276 @*/
2277 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2278 {
2279   PetscFunctionBegin;
2280   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2281   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2282   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2283   PetscFunctionReturn(0);
2284 }
2285 
2286 /*@
2287    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2288 
2289    Not Collective
2290 
2291    Input Parameter:
2292 .  A - the matrix
2293 
2294    Output Parameters:
2295 + rmap - row layout
2296 - cmap - column layout
2297 
2298    Level: advanced
2299 
2300 .seealso: `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2301 @*/
2302 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2303 {
2304   PetscFunctionBegin;
2305   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2306   PetscValidType(A, 1);
2307   if (rmap) {
2308     PetscValidPointer(rmap, 2);
2309     *rmap = A->rmap;
2310   }
2311   if (cmap) {
2312     PetscValidPointer(cmap, 3);
2313     *cmap = A->cmap;
2314   }
2315   PetscFunctionReturn(0);
2316 }
2317 
2318 /*@C
2319    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2320    using a local numbering of the nodes.
2321 
2322    Not Collective
2323 
2324    Input Parameters:
2325 +  mat - the matrix
2326 .  nrow - number of rows
2327 .  irow - the row local indices
2328 .  ncol - number of columns
2329 .  icol - the column local indices
2330 .  y -  a logically two-dimensional array of values
2331 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2332 
2333    Level: intermediate
2334 
2335    Notes:
2336    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2337       `MatSetUp()` before using this routine
2338 
2339    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2340 
2341    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2342    options cannot be mixed without intervening calls to the assembly
2343    routines.
2344 
2345    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2346    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2347 
2348    Developer Note:
2349     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2350                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2351 
2352 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2353           `MatGetValuesLocal()`
2354 @*/
2355 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2356 {
2357   PetscFunctionBeginHot;
2358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2359   PetscValidType(mat, 1);
2360   MatCheckPreallocated(mat, 1);
2361   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2362   PetscValidIntPointer(irow, 3);
2363   PetscValidIntPointer(icol, 5);
2364   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2365   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2366   if (PetscDefined(USE_DEBUG)) {
2367     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2368     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2369   }
2370 
2371   if (mat->assembled) {
2372     mat->was_assembled = PETSC_TRUE;
2373     mat->assembled     = PETSC_FALSE;
2374   }
2375   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2376   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2377   else {
2378     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2379     const PetscInt *irowm, *icolm;
2380 
2381     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2382       bufr  = buf;
2383       bufc  = buf + nrow;
2384       irowm = bufr;
2385       icolm = bufc;
2386     } else {
2387       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2388       irowm = bufr;
2389       icolm = bufc;
2390     }
2391     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2392     else irowm = irow;
2393     if (mat->cmap->mapping) {
2394       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2395         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2396       } else icolm = irowm;
2397     } else icolm = icol;
2398     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2399     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2400   }
2401   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2402   PetscFunctionReturn(0);
2403 }
2404 
2405 /*@C
2406    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2407    using a local ordering of the nodes a block at a time.
2408 
2409    Not Collective
2410 
2411    Input Parameters:
2412 +  x - the matrix
2413 .  nrow - number of rows
2414 .  irow - the row local indices
2415 .  ncol - number of columns
2416 .  icol - the column local indices
2417 .  y -  a logically two-dimensional array of values
2418 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2419 
2420    Level: intermediate
2421 
2422    Notes:
2423    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2424       `MatSetUp()` before using this routine
2425 
2426    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2427       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2428 
2429    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2430    options cannot be mixed without intervening calls to the assembly
2431    routines.
2432 
2433    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2434    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2435 
2436    Developer Note:
2437     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2438                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2439 
2440 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2441           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2442 @*/
2443 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2444 {
2445   PetscFunctionBeginHot;
2446   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2447   PetscValidType(mat, 1);
2448   MatCheckPreallocated(mat, 1);
2449   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2450   PetscValidIntPointer(irow, 3);
2451   PetscValidIntPointer(icol, 5);
2452   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2453   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2454   if (PetscDefined(USE_DEBUG)) {
2455     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2456     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);
2457   }
2458 
2459   if (mat->assembled) {
2460     mat->was_assembled = PETSC_TRUE;
2461     mat->assembled     = PETSC_FALSE;
2462   }
2463   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2464     PetscInt irbs, rbs;
2465     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2466     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2467     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2468   }
2469   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2470     PetscInt icbs, cbs;
2471     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2472     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2473     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2474   }
2475   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2476   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2477   else {
2478     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2479     const PetscInt *irowm, *icolm;
2480 
2481     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2482       bufr  = buf;
2483       bufc  = buf + nrow;
2484       irowm = bufr;
2485       icolm = bufc;
2486     } else {
2487       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2488       irowm = bufr;
2489       icolm = bufc;
2490     }
2491     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2492     else irowm = irow;
2493     if (mat->cmap->mapping) {
2494       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2495         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2496       } else icolm = irowm;
2497     } else icolm = icol;
2498     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2499     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2500   }
2501   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2502   PetscFunctionReturn(0);
2503 }
2504 
2505 /*@
2506    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2507 
2508    Collective
2509 
2510    Input Parameters:
2511 +  mat - the matrix
2512 -  x   - the vector to be multiplied
2513 
2514    Output Parameters:
2515 .  y - the result
2516 
2517    Level: developer
2518 
2519    Note:
2520    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2521    call `MatMultDiagonalBlock`(A,y,y).
2522 
2523 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2524 @*/
2525 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2526 {
2527   PetscFunctionBegin;
2528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2529   PetscValidType(mat, 1);
2530   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2531   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2532 
2533   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2534   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2535   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2536   MatCheckPreallocated(mat, 1);
2537 
2538   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2539   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2540   PetscFunctionReturn(0);
2541 }
2542 
2543 /*@
2544    MatMult - Computes the matrix-vector product, y = Ax.
2545 
2546    Neighbor-wise Collective
2547 
2548    Input Parameters:
2549 +  mat - the matrix
2550 -  x   - the vector to be multiplied
2551 
2552    Output Parameters:
2553 .  y - the result
2554 
2555    Level: beginner
2556 
2557    Note:
2558    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2559    call `MatMult`(A,y,y).
2560 
2561 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2562 @*/
2563 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2564 {
2565   PetscFunctionBegin;
2566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2567   PetscValidType(mat, 1);
2568   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2569   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2570   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2571   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2572   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2573   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);
2574   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);
2575   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);
2576   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);
2577   PetscCall(VecSetErrorIfLocked(y, 3));
2578   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2579   MatCheckPreallocated(mat, 1);
2580 
2581   PetscCall(VecLockReadPush(x));
2582   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2583   PetscUseTypeMethod(mat, mult, x, y);
2584   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2585   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2586   PetscCall(VecLockReadPop(x));
2587   PetscFunctionReturn(0);
2588 }
2589 
2590 /*@
2591    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2592 
2593    Neighbor-wise Collective
2594 
2595    Input Parameters:
2596 +  mat - the matrix
2597 -  x   - the vector to be multiplied
2598 
2599    Output Parameters:
2600 .  y - the result
2601 
2602    Level: beginner
2603 
2604    Notes:
2605    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2606    call `MatMultTranspose`(A,y,y).
2607 
2608    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2609    use `MatMultHermitianTranspose()`
2610 
2611 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2612 @*/
2613 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2614 {
2615   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2616 
2617   PetscFunctionBegin;
2618   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2619   PetscValidType(mat, 1);
2620   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2621   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2622 
2623   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2624   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2625   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2626   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);
2627   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);
2628   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);
2629   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);
2630   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2631   MatCheckPreallocated(mat, 1);
2632 
2633   if (!mat->ops->multtranspose) {
2634     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2635     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);
2636   } else op = mat->ops->multtranspose;
2637   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2638   PetscCall(VecLockReadPush(x));
2639   PetscCall((*op)(mat, x, y));
2640   PetscCall(VecLockReadPop(x));
2641   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2642   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2643   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2644   PetscFunctionReturn(0);
2645 }
2646 
2647 /*@
2648    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2649 
2650    Neighbor-wise Collective
2651 
2652    Input Parameters:
2653 +  mat - the matrix
2654 -  x   - the vector to be multilplied
2655 
2656    Output Parameters:
2657 .  y - the result
2658 
2659    Level: beginner
2660 
2661    Notes:
2662    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2663    call `MatMultHermitianTranspose`(A,y,y).
2664 
2665    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2666 
2667    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2668 
2669 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2670 @*/
2671 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2672 {
2673   PetscFunctionBegin;
2674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2675   PetscValidType(mat, 1);
2676   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2677   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2678 
2679   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2680   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2681   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2682   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);
2683   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);
2684   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);
2685   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);
2686   MatCheckPreallocated(mat, 1);
2687 
2688   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2689 #if defined(PETSC_USE_COMPLEX)
2690   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2691     PetscCall(VecLockReadPush(x));
2692     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2693     else PetscUseTypeMethod(mat, mult, x, y);
2694     PetscCall(VecLockReadPop(x));
2695   } else {
2696     Vec w;
2697     PetscCall(VecDuplicate(x, &w));
2698     PetscCall(VecCopy(x, w));
2699     PetscCall(VecConjugate(w));
2700     PetscCall(MatMultTranspose(mat, w, y));
2701     PetscCall(VecDestroy(&w));
2702     PetscCall(VecConjugate(y));
2703   }
2704   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2705 #else
2706   PetscCall(MatMultTranspose(mat, x, y));
2707 #endif
2708   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2709   PetscFunctionReturn(0);
2710 }
2711 
2712 /*@
2713     MatMultAdd -  Computes v3 = v2 + A * v1.
2714 
2715     Neighbor-wise Collective
2716 
2717     Input Parameters:
2718 +   mat - the matrix
2719 -   v1, v2 - the vectors
2720 
2721     Output Parameters:
2722 .   v3 - the result
2723 
2724     Level: beginner
2725 
2726     Note:
2727     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2728     call `MatMultAdd`(A,v1,v2,v1).
2729 
2730 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2731 @*/
2732 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2733 {
2734   PetscFunctionBegin;
2735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2736   PetscValidType(mat, 1);
2737   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2738   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2739   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2740 
2741   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2742   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2743   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);
2744   /* 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);
2745      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); */
2746   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);
2747   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);
2748   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2749   MatCheckPreallocated(mat, 1);
2750 
2751   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2752   PetscCall(VecLockReadPush(v1));
2753   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2754   PetscCall(VecLockReadPop(v1));
2755   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2756   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2757   PetscFunctionReturn(0);
2758 }
2759 
2760 /*@
2761    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2762 
2763    Neighbor-wise Collective
2764 
2765    Input Parameters:
2766 +  mat - the matrix
2767 -  v1, v2 - the vectors
2768 
2769    Output Parameters:
2770 .  v3 - the result
2771 
2772    Level: beginner
2773 
2774    Note:
2775    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2776    call `MatMultTransposeAdd`(A,v1,v2,v1).
2777 
2778 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2779 @*/
2780 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2781 {
2782   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2783 
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2786   PetscValidType(mat, 1);
2787   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2788   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2789   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2790 
2791   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2792   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2793   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);
2794   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);
2795   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);
2796   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2797   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2798   MatCheckPreallocated(mat, 1);
2799 
2800   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2801   PetscCall(VecLockReadPush(v1));
2802   PetscCall((*op)(mat, v1, v2, v3));
2803   PetscCall(VecLockReadPop(v1));
2804   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2805   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2806   PetscFunctionReturn(0);
2807 }
2808 
2809 /*@
2810    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2811 
2812    Neighbor-wise Collective
2813 
2814    Input Parameters:
2815 +  mat - the matrix
2816 -  v1, v2 - the vectors
2817 
2818    Output Parameters:
2819 .  v3 - the result
2820 
2821    Level: beginner
2822 
2823    Note:
2824    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2825    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2826 
2827 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2828 @*/
2829 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2830 {
2831   PetscFunctionBegin;
2832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2833   PetscValidType(mat, 1);
2834   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2835   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2836   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2837 
2838   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2839   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2840   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2841   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);
2842   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);
2843   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);
2844   MatCheckPreallocated(mat, 1);
2845 
2846   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2847   PetscCall(VecLockReadPush(v1));
2848   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2849   else {
2850     Vec w, z;
2851     PetscCall(VecDuplicate(v1, &w));
2852     PetscCall(VecCopy(v1, w));
2853     PetscCall(VecConjugate(w));
2854     PetscCall(VecDuplicate(v3, &z));
2855     PetscCall(MatMultTranspose(mat, w, z));
2856     PetscCall(VecDestroy(&w));
2857     PetscCall(VecConjugate(z));
2858     if (v2 != v3) {
2859       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2860     } else {
2861       PetscCall(VecAXPY(v3, 1.0, z));
2862     }
2863     PetscCall(VecDestroy(&z));
2864   }
2865   PetscCall(VecLockReadPop(v1));
2866   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2867   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2868   PetscFunctionReturn(0);
2869 }
2870 
2871 /*@C
2872    MatGetFactorType - gets the type of factorization it is
2873 
2874    Not Collective
2875 
2876    Input Parameters:
2877 .  mat - the matrix
2878 
2879    Output Parameters:
2880 .  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`
2881 
2882    Level: intermediate
2883 
2884 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2885           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2886 @*/
2887 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2888 {
2889   PetscFunctionBegin;
2890   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2891   PetscValidType(mat, 1);
2892   PetscValidPointer(t, 2);
2893   *t = mat->factortype;
2894   PetscFunctionReturn(0);
2895 }
2896 
2897 /*@C
2898    MatSetFactorType - sets the type of factorization it is
2899 
2900    Logically Collective
2901 
2902    Input Parameters:
2903 +  mat - the matrix
2904 -  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`
2905 
2906    Level: intermediate
2907 
2908 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2909           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2910 @*/
2911 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2912 {
2913   PetscFunctionBegin;
2914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2915   PetscValidType(mat, 1);
2916   mat->factortype = t;
2917   PetscFunctionReturn(0);
2918 }
2919 
2920 /*@C
2921    MatGetInfo - Returns information about matrix storage (number of
2922    nonzeros, memory, etc.).
2923 
2924    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2925 
2926    Input Parameters:
2927 +  mat - the matrix
2928 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2929 
2930    Output Parameters:
2931 .  info - matrix information context
2932 
2933    Notes:
2934    The `MatInfo` context contains a variety of matrix data, including
2935    number of nonzeros allocated and used, number of mallocs during
2936    matrix assembly, etc.  Additional information for factored matrices
2937    is provided (such as the fill ratio, number of mallocs during
2938    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2939    when using the runtime options
2940 $       -info -mat_view ::ascii_info
2941 
2942    Example for C/C++ Users:
2943    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2944    data within the MatInfo context.  For example,
2945 .vb
2946       MatInfo info;
2947       Mat     A;
2948       double  mal, nz_a, nz_u;
2949 
2950       MatGetInfo(A,MAT_LOCAL,&info);
2951       mal  = info.mallocs;
2952       nz_a = info.nz_allocated;
2953 .ve
2954 
2955    Example for Fortran Users:
2956    Fortran users should declare info as a double precision
2957    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2958    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2959    a complete list of parameter names.
2960 .vb
2961       double  precision info(MAT_INFO_SIZE)
2962       double  precision mal, nz_a
2963       Mat     A
2964       integer ierr
2965 
2966       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2967       mal = info(MAT_INFO_MALLOCS)
2968       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2969 .ve
2970 
2971     Level: intermediate
2972 
2973     Developer Note:
2974     Fortran interface is not autogenerated as the
2975     interface definition cannot be generated correctly [due to MatInfo]
2976 
2977 .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()`
2978 @*/
2979 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2980 {
2981   PetscFunctionBegin;
2982   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2983   PetscValidType(mat, 1);
2984   PetscValidPointer(info, 3);
2985   MatCheckPreallocated(mat, 1);
2986   PetscUseTypeMethod(mat, getinfo, flag, info);
2987   PetscFunctionReturn(0);
2988 }
2989 
2990 /*
2991    This is used by external packages where it is not easy to get the info from the actual
2992    matrix factorization.
2993 */
2994 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2995 {
2996   PetscFunctionBegin;
2997   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2998   PetscFunctionReturn(0);
2999 }
3000 
3001 /*@C
3002    MatLUFactor - Performs in-place LU factorization of matrix.
3003 
3004    Collective
3005 
3006    Input Parameters:
3007 +  mat - the matrix
3008 .  row - row permutation
3009 .  col - column permutation
3010 -  info - options for factorization, includes
3011 .vb
3012           fill - expected fill as ratio of original fill.
3013           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3014                    Run with the option -info to determine an optimal value to use
3015 .ve
3016    Level: developer
3017 
3018    Notes:
3019    Most users should employ the `KSP` interface for linear solvers
3020    instead of working directly with matrix algebra routines such as this.
3021    See, e.g., `KSPCreate()`.
3022 
3023    This changes the state of the matrix to a factored matrix; it cannot be used
3024    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3025 
3026    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3027    when not using `KSP`.
3028 
3029    Developer Note:
3030    The Fortran interface is not autogenerated as the
3031    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3032 
3033 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3034           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3035 @*/
3036 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3037 {
3038   MatFactorInfo tinfo;
3039 
3040   PetscFunctionBegin;
3041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3042   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3043   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3044   if (info) PetscValidPointer(info, 4);
3045   PetscValidType(mat, 1);
3046   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3047   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3048   MatCheckPreallocated(mat, 1);
3049   if (!info) {
3050     PetscCall(MatFactorInfoInitialize(&tinfo));
3051     info = &tinfo;
3052   }
3053 
3054   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3055   PetscUseTypeMethod(mat, lufactor, row, col, info);
3056   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3057   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3058   PetscFunctionReturn(0);
3059 }
3060 
3061 /*@C
3062    MatILUFactor - Performs in-place ILU factorization of matrix.
3063 
3064    Collective
3065 
3066    Input Parameters:
3067 +  mat - the matrix
3068 .  row - row permutation
3069 .  col - column permutation
3070 -  info - structure containing
3071 .vb
3072       levels - number of levels of fill.
3073       expected fill - as ratio of original fill.
3074       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3075                 missing diagonal entries)
3076 .ve
3077 
3078    Level: developer
3079 
3080    Notes:
3081    Most users should employ the `KSP` interface for linear solvers
3082    instead of working directly with matrix algebra routines such as this.
3083    See, e.g., `KSPCreate()`.
3084 
3085    Probably really in-place only when level of fill is zero, otherwise allocates
3086    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3087    when not using `KSP`.
3088 
3089    Developer Note:
3090    The Fortran interface is not autogenerated as the
3091    interface definition cannot be generated correctly [due to MatFactorInfo]
3092 
3093 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3094 @*/
3095 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3096 {
3097   PetscFunctionBegin;
3098   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3099   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3100   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3101   PetscValidPointer(info, 4);
3102   PetscValidType(mat, 1);
3103   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3104   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3105   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3106   MatCheckPreallocated(mat, 1);
3107 
3108   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3109   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3110   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3111   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3112   PetscFunctionReturn(0);
3113 }
3114 
3115 /*@C
3116    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3117    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3118 
3119    Collective on fact
3120 
3121    Input Parameters:
3122 +  fact - the factor matrix obtained with `MatGetFactor()`
3123 .  mat - the matrix
3124 .  row, col - row and column permutations
3125 -  info - options for factorization, includes
3126 .vb
3127           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3128           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3129 .ve
3130 
3131    Level: developer
3132 
3133    Notes:
3134     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3135 
3136    Most users should employ the simplified `KSP` interface for linear solvers
3137    instead of working directly with matrix algebra routines such as this.
3138    See, e.g., `KSPCreate()`.
3139 
3140    Developer Note:
3141    The Fortran interface is not autogenerated as the
3142    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3143 
3144 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3145 @*/
3146 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3147 {
3148   MatFactorInfo tinfo;
3149 
3150   PetscFunctionBegin;
3151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3152   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3153   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3154   if (info) PetscValidPointer(info, 5);
3155   PetscValidType(mat, 2);
3156   PetscValidPointer(fact, 1);
3157   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3158   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3159   if (!(fact)->ops->lufactorsymbolic) {
3160     MatSolverType stype;
3161     PetscCall(MatFactorGetSolverType(fact, &stype));
3162     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3163   }
3164   MatCheckPreallocated(mat, 2);
3165   if (!info) {
3166     PetscCall(MatFactorInfoInitialize(&tinfo));
3167     info = &tinfo;
3168   }
3169 
3170   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3171   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3172   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3173   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3174   PetscFunctionReturn(0);
3175 }
3176 
3177 /*@C
3178    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3179    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3180 
3181    Collective on fact
3182 
3183    Input Parameters:
3184 +  fact - the factor matrix obtained with `MatGetFactor()`
3185 .  mat - the matrix
3186 -  info - options for factorization
3187 
3188    Level: developer
3189 
3190    Notes:
3191    See `MatLUFactor()` for in-place factorization.  See
3192    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3193 
3194    Most users should employ the `KSP` interface for linear solvers
3195    instead of working directly with matrix algebra routines such as this.
3196    See, e.g., `KSPCreate()`.
3197 
3198     Developer Note:
3199     The Fortran interface is not autogenerated as the
3200     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3201 
3202 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3203 @*/
3204 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3205 {
3206   MatFactorInfo tinfo;
3207 
3208   PetscFunctionBegin;
3209   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3210   PetscValidType(mat, 2);
3211   PetscValidPointer(fact, 1);
3212   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3213   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3214   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,
3215              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3216 
3217   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3218   MatCheckPreallocated(mat, 2);
3219   if (!info) {
3220     PetscCall(MatFactorInfoInitialize(&tinfo));
3221     info = &tinfo;
3222   }
3223 
3224   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3225   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3226   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3227   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3228   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3229   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3230   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3231   PetscFunctionReturn(0);
3232 }
3233 
3234 /*@C
3235    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3236    symmetric matrix.
3237 
3238    Collective
3239 
3240    Input Parameters:
3241 +  mat - the matrix
3242 .  perm - row and column permutations
3243 -  f - expected fill as ratio of original fill
3244 
3245    Level: developer
3246 
3247    Notes:
3248    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3249    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3250 
3251    Most users should employ the `KSP` interface for linear solvers
3252    instead of working directly with matrix algebra routines such as this.
3253    See, e.g., `KSPCreate()`.
3254 
3255    Developer Note:
3256    The Fortran interface is not autogenerated as the
3257    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3258 
3259 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3260           `MatGetOrdering()`
3261 @*/
3262 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3263 {
3264   MatFactorInfo tinfo;
3265 
3266   PetscFunctionBegin;
3267   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3268   PetscValidType(mat, 1);
3269   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3270   if (info) PetscValidPointer(info, 3);
3271   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3272   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3273   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3274   MatCheckPreallocated(mat, 1);
3275   if (!info) {
3276     PetscCall(MatFactorInfoInitialize(&tinfo));
3277     info = &tinfo;
3278   }
3279 
3280   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3281   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3282   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3283   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3284   PetscFunctionReturn(0);
3285 }
3286 
3287 /*@C
3288    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3289    of a symmetric matrix.
3290 
3291    Collective on fact
3292 
3293    Input Parameters:
3294 +  fact - the factor matrix obtained with `MatGetFactor()`
3295 .  mat - the matrix
3296 .  perm - row and column permutations
3297 -  info - options for factorization, includes
3298 .vb
3299           fill - expected fill as ratio of original fill.
3300           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3301                    Run with the option -info to determine an optimal value to use
3302 .ve
3303 
3304    Level: developer
3305 
3306    Notes:
3307    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3308    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3309 
3310    Most users should employ the `KSP` interface for linear solvers
3311    instead of working directly with matrix algebra routines such as this.
3312    See, e.g., `KSPCreate()`.
3313 
3314    Developer Note:
3315    The Fortran interface is not autogenerated as the
3316    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3317 
3318 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3319           `MatGetOrdering()`
3320 @*/
3321 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3322 {
3323   MatFactorInfo tinfo;
3324 
3325   PetscFunctionBegin;
3326   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3327   PetscValidType(mat, 2);
3328   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3329   if (info) PetscValidPointer(info, 4);
3330   PetscValidPointer(fact, 1);
3331   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3332   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3333   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3334   if (!(fact)->ops->choleskyfactorsymbolic) {
3335     MatSolverType stype;
3336     PetscCall(MatFactorGetSolverType(fact, &stype));
3337     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3338   }
3339   MatCheckPreallocated(mat, 2);
3340   if (!info) {
3341     PetscCall(MatFactorInfoInitialize(&tinfo));
3342     info = &tinfo;
3343   }
3344 
3345   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3346   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3347   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3348   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3349   PetscFunctionReturn(0);
3350 }
3351 
3352 /*@C
3353    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3354    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3355    `MatCholeskyFactorSymbolic()`.
3356 
3357    Collective on fact
3358 
3359    Input Parameters:
3360 +  fact - the factor matrix obtained with `MatGetFactor()`
3361 .  mat - the initial matrix
3362 .  info - options for factorization
3363 -  fact - the symbolic factor of mat
3364 
3365    Level: developer
3366 
3367    Note:
3368    Most users should employ the `KSP` interface for linear solvers
3369    instead of working directly with matrix algebra routines such as this.
3370    See, e.g., `KSPCreate()`.
3371 
3372    Developer Note:
3373    The Fortran interface is not autogenerated as the
3374    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3375 
3376 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3377 @*/
3378 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3379 {
3380   MatFactorInfo tinfo;
3381 
3382   PetscFunctionBegin;
3383   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3384   PetscValidType(mat, 2);
3385   PetscValidPointer(fact, 1);
3386   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3387   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3388   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3389   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,
3390              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3391   MatCheckPreallocated(mat, 2);
3392   if (!info) {
3393     PetscCall(MatFactorInfoInitialize(&tinfo));
3394     info = &tinfo;
3395   }
3396 
3397   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3398   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3399   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3400   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3401   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3402   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3403   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3404   PetscFunctionReturn(0);
3405 }
3406 
3407 /*@
3408    MatQRFactor - Performs in-place QR factorization of matrix.
3409 
3410    Collective
3411 
3412    Input Parameters:
3413 +  mat - the matrix
3414 .  col - column permutation
3415 -  info - options for factorization, includes
3416 .vb
3417           fill - expected fill as ratio of original fill.
3418           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3419                    Run with the option -info to determine an optimal value to use
3420 .ve
3421 
3422    Level: developer
3423 
3424    Notes:
3425    Most users should employ the `KSP` interface for linear solvers
3426    instead of working directly with matrix algebra routines such as this.
3427    See, e.g., `KSPCreate()`.
3428 
3429    This changes the state of the matrix to a factored matrix; it cannot be used
3430    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3431 
3432    Developer Note:
3433    The Fortran interface is not autogenerated as the
3434    interface definition cannot be generated correctly [due to MatFactorInfo]
3435 
3436 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3437           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3438 @*/
3439 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3440 {
3441   PetscFunctionBegin;
3442   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3443   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3444   if (info) PetscValidPointer(info, 3);
3445   PetscValidType(mat, 1);
3446   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3447   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3448   MatCheckPreallocated(mat, 1);
3449   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3450   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3451   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3452   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3453   PetscFunctionReturn(0);
3454 }
3455 
3456 /*@
3457    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3458    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3459 
3460    Collective on fact
3461 
3462    Input Parameters:
3463 +  fact - the factor matrix obtained with `MatGetFactor()`
3464 .  mat - the matrix
3465 .  col - column permutation
3466 -  info - options for factorization, includes
3467 .vb
3468           fill - expected fill as ratio of original fill.
3469           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3470                    Run with the option -info to determine an optimal value to use
3471 .ve
3472 
3473    Level: developer
3474 
3475    Note:
3476    Most users should employ the `KSP` interface for linear solvers
3477    instead of working directly with matrix algebra routines such as this.
3478    See, e.g., `KSPCreate()`.
3479 
3480    Developer Note:
3481    The Fortran interface is not autogenerated as the
3482    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3483 
3484 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3485 @*/
3486 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3487 {
3488   MatFactorInfo tinfo;
3489 
3490   PetscFunctionBegin;
3491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3492   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3493   if (info) PetscValidPointer(info, 4);
3494   PetscValidType(mat, 2);
3495   PetscValidPointer(fact, 1);
3496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3498   MatCheckPreallocated(mat, 2);
3499   if (!info) {
3500     PetscCall(MatFactorInfoInitialize(&tinfo));
3501     info = &tinfo;
3502   }
3503 
3504   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3505   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3506   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3507   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3508   PetscFunctionReturn(0);
3509 }
3510 
3511 /*@
3512    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3513    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3514 
3515    Collective on fact
3516 
3517    Input Parameters:
3518 +  fact - the factor matrix obtained with `MatGetFactor()`
3519 .  mat - the matrix
3520 -  info - options for factorization
3521 
3522    Level: developer
3523 
3524    Notes:
3525    See `MatQRFactor()` for in-place factorization.
3526 
3527    Most users should employ the `KSP` interface for linear solvers
3528    instead of working directly with matrix algebra routines such as this.
3529    See, e.g., `KSPCreate()`.
3530 
3531    Developer Note:
3532    The Fortran interface is not autogenerated as the
3533    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3534 
3535 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3536 @*/
3537 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3538 {
3539   MatFactorInfo tinfo;
3540 
3541   PetscFunctionBegin;
3542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3543   PetscValidType(mat, 2);
3544   PetscValidPointer(fact, 1);
3545   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3546   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3547   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,
3548              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3549 
3550   MatCheckPreallocated(mat, 2);
3551   if (!info) {
3552     PetscCall(MatFactorInfoInitialize(&tinfo));
3553     info = &tinfo;
3554   }
3555 
3556   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3557   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3558   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3559   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3560   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3561   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3562   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3563   PetscFunctionReturn(0);
3564 }
3565 
3566 /*@
3567    MatSolve - Solves A x = b, given a factored matrix.
3568 
3569    Neighbor-wise Collective
3570 
3571    Input Parameters:
3572 +  mat - the factored matrix
3573 -  b - the right-hand-side vector
3574 
3575    Output Parameter:
3576 .  x - the result vector
3577 
3578    Level: developer
3579 
3580    Notes:
3581    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3582    call `MatSolve`(A,x,x).
3583 
3584    Most users should employ the `KSP` interface for linear solvers
3585    instead of working directly with matrix algebra routines such as this.
3586    See, e.g., `KSPCreate()`.
3587 
3588 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3589 @*/
3590 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3591 {
3592   PetscFunctionBegin;
3593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3594   PetscValidType(mat, 1);
3595   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3596   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3597   PetscCheckSameComm(mat, 1, b, 2);
3598   PetscCheckSameComm(mat, 1, x, 3);
3599   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3600   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);
3601   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);
3602   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);
3603   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3604   MatCheckPreallocated(mat, 1);
3605 
3606   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3607   if (mat->factorerrortype) {
3608     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3609     PetscCall(VecSetInf(x));
3610   } else PetscUseTypeMethod(mat, solve, b, x);
3611   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3612   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3613   PetscFunctionReturn(0);
3614 }
3615 
3616 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3617 {
3618   Vec      b, x;
3619   PetscInt N, i;
3620   PetscErrorCode (*f)(Mat, Vec, Vec);
3621   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3622 
3623   PetscFunctionBegin;
3624   if (A->factorerrortype) {
3625     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3626     PetscCall(MatSetInf(X));
3627     PetscFunctionReturn(0);
3628   }
3629   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3630   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3631   PetscCall(MatBoundToCPU(A, &Abound));
3632   if (!Abound) {
3633     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3634     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3635   }
3636 #if defined(PETSC_HAVE_CUDA)
3637   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3638   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3639 #elif (PETSC_HAVE_HIP)
3640   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3641   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3642 #endif
3643   PetscCall(MatGetSize(B, NULL, &N));
3644   for (i = 0; i < N; i++) {
3645     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3646     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3647     PetscCall((*f)(A, b, x));
3648     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3649     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3650   }
3651   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3652   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3653   PetscFunctionReturn(0);
3654 }
3655 
3656 /*@
3657    MatMatSolve - Solves A X = B, given a factored matrix.
3658 
3659    Neighbor-wise Collective
3660 
3661    Input Parameters:
3662 +  A - the factored matrix
3663 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3664 
3665    Output Parameter:
3666 .  X - the result matrix (dense matrix)
3667 
3668    Level: developer
3669 
3670    Note:
3671    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3672    otherwise, `B` and `X` cannot be the same.
3673 
3674 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3675 @*/
3676 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3677 {
3678   PetscFunctionBegin;
3679   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3680   PetscValidType(A, 1);
3681   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3682   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3683   PetscCheckSameComm(A, 1, B, 2);
3684   PetscCheckSameComm(A, 1, X, 3);
3685   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);
3686   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);
3687   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");
3688   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3689   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3690   MatCheckPreallocated(A, 1);
3691 
3692   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3693   if (!A->ops->matsolve) {
3694     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3695     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3696   } else PetscUseTypeMethod(A, matsolve, B, X);
3697   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3698   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3699   PetscFunctionReturn(0);
3700 }
3701 
3702 /*@
3703    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3704 
3705    Neighbor-wise Collective
3706 
3707    Input Parameters:
3708 +  A - the factored matrix
3709 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3710 
3711    Output Parameter:
3712 .  X - the result matrix (dense matrix)
3713 
3714    Level: developer
3715 
3716    Note:
3717    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3718    call `MatMatSolveTranspose`(A,X,X).
3719 
3720 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3721 @*/
3722 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3723 {
3724   PetscFunctionBegin;
3725   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3726   PetscValidType(A, 1);
3727   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3728   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3729   PetscCheckSameComm(A, 1, B, 2);
3730   PetscCheckSameComm(A, 1, X, 3);
3731   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3732   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);
3733   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);
3734   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);
3735   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");
3736   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3737   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3738   MatCheckPreallocated(A, 1);
3739 
3740   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3741   if (!A->ops->matsolvetranspose) {
3742     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3743     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3744   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3745   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3746   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3747   PetscFunctionReturn(0);
3748 }
3749 
3750 /*@
3751    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3752 
3753    Neighbor-wise Collective
3754 
3755    Input Parameters:
3756 +  A - the factored matrix
3757 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3758 
3759    Output Parameter:
3760 .  X - the result matrix (dense matrix)
3761 
3762    Level: developer
3763 
3764    Note:
3765    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
3766    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3767 
3768 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3769 @*/
3770 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3771 {
3772   PetscFunctionBegin;
3773   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3774   PetscValidType(A, 1);
3775   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3776   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3777   PetscCheckSameComm(A, 1, Bt, 2);
3778   PetscCheckSameComm(A, 1, X, 3);
3779 
3780   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3781   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);
3782   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);
3783   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");
3784   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3785   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3786   MatCheckPreallocated(A, 1);
3787 
3788   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3789   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3790   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3791   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3792   PetscFunctionReturn(0);
3793 }
3794 
3795 /*@
3796    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3797                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3798 
3799    Neighbor-wise Collective
3800 
3801    Input Parameters:
3802 +  mat - the factored matrix
3803 -  b - the right-hand-side vector
3804 
3805    Output Parameter:
3806 .  x - the result vector
3807 
3808    Level: developer
3809 
3810    Notes:
3811    `MatSolve()` should be used for most applications, as it performs
3812    a forward solve followed by a backward solve.
3813 
3814    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3815    call `MatForwardSolve`(A,x,x).
3816 
3817    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3818    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3819    `MatForwardSolve()` solves U^T*D y = b, and
3820    `MatBackwardSolve()` solves U x = y.
3821    Thus they do not provide a symmetric preconditioner.
3822 
3823 .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3824 @*/
3825 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3826 {
3827   PetscFunctionBegin;
3828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3829   PetscValidType(mat, 1);
3830   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3831   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3832   PetscCheckSameComm(mat, 1, b, 2);
3833   PetscCheckSameComm(mat, 1, x, 3);
3834   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3835   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);
3836   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);
3837   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);
3838   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3839   MatCheckPreallocated(mat, 1);
3840 
3841   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3842   PetscUseTypeMethod(mat, forwardsolve, b, x);
3843   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3844   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3845   PetscFunctionReturn(0);
3846 }
3847 
3848 /*@
3849    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3850                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3851 
3852    Neighbor-wise Collective
3853 
3854    Input Parameters:
3855 +  mat - the factored matrix
3856 -  b - the right-hand-side vector
3857 
3858    Output Parameter:
3859 .  x - the result vector
3860 
3861    Level: developer
3862 
3863    Notes:
3864    `MatSolve()` should be used for most applications, as it performs
3865    a forward solve followed by a backward solve.
3866 
3867    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3868    call `MatBackwardSolve`(A,x,x).
3869 
3870    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3871    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3872    `MatForwardSolve()` solves U^T*D y = b, and
3873    `MatBackwardSolve()` solves U x = y.
3874    Thus they do not provide a symmetric preconditioner.
3875 
3876 .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3877 @*/
3878 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3879 {
3880   PetscFunctionBegin;
3881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3882   PetscValidType(mat, 1);
3883   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3884   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3885   PetscCheckSameComm(mat, 1, b, 2);
3886   PetscCheckSameComm(mat, 1, x, 3);
3887   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3888   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);
3889   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);
3890   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);
3891   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3892   MatCheckPreallocated(mat, 1);
3893 
3894   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3895   PetscUseTypeMethod(mat, backwardsolve, b, x);
3896   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3897   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3898   PetscFunctionReturn(0);
3899 }
3900 
3901 /*@
3902    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3903 
3904    Neighbor-wise Collective
3905 
3906    Input Parameters:
3907 +  mat - the factored matrix
3908 .  b - the right-hand-side vector
3909 -  y - the vector to be added to
3910 
3911    Output Parameter:
3912 .  x - the result vector
3913 
3914    Level: developer
3915 
3916    Note:
3917    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3918    call `MatSolveAdd`(A,x,y,x).
3919 
3920 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3921 @*/
3922 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3923 {
3924   PetscScalar one = 1.0;
3925   Vec         tmp;
3926 
3927   PetscFunctionBegin;
3928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3929   PetscValidType(mat, 1);
3930   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3931   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3932   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3933   PetscCheckSameComm(mat, 1, b, 2);
3934   PetscCheckSameComm(mat, 1, y, 3);
3935   PetscCheckSameComm(mat, 1, x, 4);
3936   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3937   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);
3938   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);
3939   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);
3940   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);
3941   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);
3942   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3943   MatCheckPreallocated(mat, 1);
3944 
3945   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3946   if (mat->factorerrortype) {
3947     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3948     PetscCall(VecSetInf(x));
3949   } else if (mat->ops->solveadd) {
3950     PetscUseTypeMethod(mat, solveadd, b, y, x);
3951   } else {
3952     /* do the solve then the add manually */
3953     if (x != y) {
3954       PetscCall(MatSolve(mat, b, x));
3955       PetscCall(VecAXPY(x, one, y));
3956     } else {
3957       PetscCall(VecDuplicate(x, &tmp));
3958       PetscCall(VecCopy(x, tmp));
3959       PetscCall(MatSolve(mat, b, x));
3960       PetscCall(VecAXPY(x, one, tmp));
3961       PetscCall(VecDestroy(&tmp));
3962     }
3963   }
3964   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3965   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3966   PetscFunctionReturn(0);
3967 }
3968 
3969 /*@
3970    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3971 
3972    Neighbor-wise Collective
3973 
3974    Input Parameters:
3975 +  mat - the factored matrix
3976 -  b - the right-hand-side vector
3977 
3978    Output Parameter:
3979 .  x - the result vector
3980 
3981    Level: developer
3982 
3983    Notes:
3984    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3985    call `MatSolveTranspose`(A,x,x).
3986 
3987    Most users should employ the `KSP` interface for linear solvers
3988    instead of working directly with matrix algebra routines such as this.
3989    See, e.g., `KSPCreate()`.
3990 
3991 .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3992 @*/
3993 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3994 {
3995   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3996 
3997   PetscFunctionBegin;
3998   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3999   PetscValidType(mat, 1);
4000   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4001   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4002   PetscCheckSameComm(mat, 1, b, 2);
4003   PetscCheckSameComm(mat, 1, x, 3);
4004   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4005   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);
4006   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);
4007   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4008   MatCheckPreallocated(mat, 1);
4009   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4010   if (mat->factorerrortype) {
4011     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4012     PetscCall(VecSetInf(x));
4013   } else {
4014     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4015     PetscCall((*f)(mat, b, x));
4016   }
4017   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4018   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4019   PetscFunctionReturn(0);
4020 }
4021 
4022 /*@
4023    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4024                       factored matrix.
4025 
4026    Neighbor-wise Collective
4027 
4028    Input Parameters:
4029 +  mat - the factored matrix
4030 .  b - the right-hand-side vector
4031 -  y - the vector to be added to
4032 
4033    Output Parameter:
4034 .  x - the result vector
4035 
4036    Level: developer
4037 
4038    Note:
4039    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4040    call `MatSolveTransposeAdd`(A,x,y,x).
4041 
4042 .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4043 @*/
4044 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4045 {
4046   PetscScalar one = 1.0;
4047   Vec         tmp;
4048   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4049 
4050   PetscFunctionBegin;
4051   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4052   PetscValidType(mat, 1);
4053   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4054   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4055   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4056   PetscCheckSameComm(mat, 1, b, 2);
4057   PetscCheckSameComm(mat, 1, y, 3);
4058   PetscCheckSameComm(mat, 1, x, 4);
4059   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4060   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);
4061   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);
4062   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);
4063   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);
4064   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
4065   MatCheckPreallocated(mat, 1);
4066 
4067   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4068   if (mat->factorerrortype) {
4069     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4070     PetscCall(VecSetInf(x));
4071   } else if (f) {
4072     PetscCall((*f)(mat, b, y, x));
4073   } else {
4074     /* do the solve then the add manually */
4075     if (x != y) {
4076       PetscCall(MatSolveTranspose(mat, b, x));
4077       PetscCall(VecAXPY(x, one, y));
4078     } else {
4079       PetscCall(VecDuplicate(x, &tmp));
4080       PetscCall(VecCopy(x, tmp));
4081       PetscCall(MatSolveTranspose(mat, b, x));
4082       PetscCall(VecAXPY(x, one, tmp));
4083       PetscCall(VecDestroy(&tmp));
4084     }
4085   }
4086   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4087   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4088   PetscFunctionReturn(0);
4089 }
4090 
4091 /*@
4092    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4093 
4094    Neighbor-wise Collective
4095 
4096    Input Parameters:
4097 +  mat - the matrix
4098 .  b - the right hand side
4099 .  omega - the relaxation factor
4100 .  flag - flag indicating the type of SOR (see below)
4101 .  shift -  diagonal shift
4102 .  its - the number of iterations
4103 -  lits - the number of local iterations
4104 
4105    Output Parameter:
4106 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4107 
4108    SOR Flags:
4109 +     `SOR_FORWARD_SWEEP` - forward SOR
4110 .     `SOR_BACKWARD_SWEEP` - backward SOR
4111 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4112 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4113 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4114 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4115 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4116 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4117          upper/lower triangular part of matrix to
4118          vector (with omega)
4119 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4120 
4121    Level: developer
4122 
4123    Notes:
4124    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4125    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4126    on each processor.
4127 
4128    Application programmers will not generally use `MatSOR()` directly,
4129    but instead will employ the `KSP`/`PC` interface.
4130 
4131    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4132 
4133    Most users should employ the `KSP` interface for linear solvers
4134    instead of working directly with matrix algebra routines such as this.
4135    See, e.g., `KSPCreate()`.
4136 
4137    Vectors `x` and `b` CANNOT be the same
4138 
4139    Notes for Advanced Users:
4140    The flags are implemented as bitwise inclusive or operations.
4141    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4142    to specify a zero initial guess for SSOR.
4143 
4144    Developer Note:
4145    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4146 
4147 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4148 @*/
4149 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4150 {
4151   PetscFunctionBegin;
4152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4153   PetscValidType(mat, 1);
4154   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4155   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4156   PetscCheckSameComm(mat, 1, b, 2);
4157   PetscCheckSameComm(mat, 1, x, 8);
4158   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4159   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4160   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);
4161   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);
4162   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);
4163   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4164   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4165   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4166 
4167   MatCheckPreallocated(mat, 1);
4168   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4169   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4170   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4171   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4172   PetscFunctionReturn(0);
4173 }
4174 
4175 /*
4176       Default matrix copy routine.
4177 */
4178 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4179 {
4180   PetscInt           i, rstart = 0, rend = 0, nz;
4181   const PetscInt    *cwork;
4182   const PetscScalar *vwork;
4183 
4184   PetscFunctionBegin;
4185   if (B->assembled) PetscCall(MatZeroEntries(B));
4186   if (str == SAME_NONZERO_PATTERN) {
4187     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4188     for (i = rstart; i < rend; i++) {
4189       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4190       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4191       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4192     }
4193   } else {
4194     PetscCall(MatAYPX(B, 0.0, A, str));
4195   }
4196   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4197   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4198   PetscFunctionReturn(0);
4199 }
4200 
4201 /*@
4202    MatCopy - Copies a matrix to another matrix.
4203 
4204    Collective
4205 
4206    Input Parameters:
4207 +  A - the matrix
4208 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4209 
4210    Output Parameter:
4211 .  B - where the copy is put
4212 
4213    Level: intermediate
4214 
4215    Notes:
4216    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4217 
4218    `MatCopy()` copies the matrix entries of a matrix to another existing
4219    matrix (after first zeroing the second matrix).  A related routine is
4220    `MatConvert()`, which first creates a new matrix and then copies the data.
4221 
4222 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4223 @*/
4224 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4225 {
4226   PetscInt i;
4227 
4228   PetscFunctionBegin;
4229   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4230   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4231   PetscValidType(A, 1);
4232   PetscValidType(B, 2);
4233   PetscCheckSameComm(A, 1, B, 2);
4234   MatCheckPreallocated(B, 2);
4235   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4236   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4237   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,
4238              A->cmap->N, B->cmap->N);
4239   MatCheckPreallocated(A, 1);
4240   if (A == B) PetscFunctionReturn(0);
4241 
4242   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4243   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4244   else PetscCall(MatCopy_Basic(A, B, str));
4245 
4246   B->stencil.dim = A->stencil.dim;
4247   B->stencil.noc = A->stencil.noc;
4248   for (i = 0; i <= A->stencil.dim; i++) {
4249     B->stencil.dims[i]   = A->stencil.dims[i];
4250     B->stencil.starts[i] = A->stencil.starts[i];
4251   }
4252 
4253   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4254   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4255   PetscFunctionReturn(0);
4256 }
4257 
4258 /*@C
4259    MatConvert - Converts a matrix to another matrix, either of the same
4260    or different type.
4261 
4262    Collective
4263 
4264    Input Parameters:
4265 +  mat - the matrix
4266 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4267    same type as the original matrix.
4268 -  reuse - denotes if the destination matrix is to be created or reused.
4269    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
4270    `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).
4271 
4272    Output Parameter:
4273 .  M - pointer to place new matrix
4274 
4275    Level: intermediate
4276 
4277    Notes:
4278    `MatConvert()` first creates a new matrix and then copies the data from
4279    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4280    entries of one matrix to another already existing matrix context.
4281 
4282    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4283    the MPI communicator of the generated matrix is always the same as the communicator
4284    of the input matrix.
4285 
4286 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4287 @*/
4288 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4289 {
4290   PetscBool  sametype, issame, flg;
4291   PetscBool3 issymmetric, ishermitian;
4292   char       convname[256], mtype[256];
4293   Mat        B;
4294 
4295   PetscFunctionBegin;
4296   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4297   PetscValidType(mat, 1);
4298   PetscValidPointer(M, 4);
4299   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4300   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4301   MatCheckPreallocated(mat, 1);
4302 
4303   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4304   if (flg) newtype = mtype;
4305 
4306   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4307   PetscCall(PetscStrcmp(newtype, "same", &issame));
4308   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4309   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");
4310 
4311   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4312     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4313     PetscFunctionReturn(0);
4314   }
4315 
4316   /* Cache Mat options because some converters use MatHeaderReplace  */
4317   issymmetric = mat->symmetric;
4318   ishermitian = mat->hermitian;
4319 
4320   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4321     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4322     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4323   } else {
4324     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4325     const char *prefix[3]                                 = {"seq", "mpi", ""};
4326     PetscInt    i;
4327     /*
4328        Order of precedence:
4329        0) See if newtype is a superclass of the current matrix.
4330        1) See if a specialized converter is known to the current matrix.
4331        2) See if a specialized converter is known to the desired matrix class.
4332        3) See if a good general converter is registered for the desired class
4333           (as of 6/27/03 only MATMPIADJ falls into this category).
4334        4) See if a good general converter is known for the current matrix.
4335        5) Use a really basic converter.
4336     */
4337 
4338     /* 0) See if newtype is a superclass of the current matrix.
4339           i.e mat is mpiaij and newtype is aij */
4340     for (i = 0; i < 2; i++) {
4341       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4342       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4343       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4344       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4345       if (flg) {
4346         if (reuse == MAT_INPLACE_MATRIX) {
4347           PetscCall(PetscInfo(mat, "Early return\n"));
4348           PetscFunctionReturn(0);
4349         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4350           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4351           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4352           PetscFunctionReturn(0);
4353         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4354           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4355           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4356           PetscFunctionReturn(0);
4357         }
4358       }
4359     }
4360     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4361     for (i = 0; i < 3; i++) {
4362       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4367       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4368       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4369       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4370       if (conv) goto foundconv;
4371     }
4372 
4373     /* 2)  See if a specialized converter is known to the desired matrix class. */
4374     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4375     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4376     PetscCall(MatSetType(B, newtype));
4377     for (i = 0; i < 3; i++) {
4378       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4381       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4382       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4383       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4384       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4385       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4386       if (conv) {
4387         PetscCall(MatDestroy(&B));
4388         goto foundconv;
4389       }
4390     }
4391 
4392     /* 3) See if a good general converter is registered for the desired class */
4393     conv = B->ops->convertfrom;
4394     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4395     PetscCall(MatDestroy(&B));
4396     if (conv) goto foundconv;
4397 
4398     /* 4) See if a good general converter is known for the current matrix */
4399     if (mat->ops->convert) conv = mat->ops->convert;
4400     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4401     if (conv) goto foundconv;
4402 
4403     /* 5) Use a really basic converter. */
4404     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4405     conv = MatConvert_Basic;
4406 
4407   foundconv:
4408     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4409     PetscCall((*conv)(mat, newtype, reuse, M));
4410     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4411       /* the block sizes must be same if the mappings are copied over */
4412       (*M)->rmap->bs = mat->rmap->bs;
4413       (*M)->cmap->bs = mat->cmap->bs;
4414       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4415       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4416       (*M)->rmap->mapping = mat->rmap->mapping;
4417       (*M)->cmap->mapping = mat->cmap->mapping;
4418     }
4419     (*M)->stencil.dim = mat->stencil.dim;
4420     (*M)->stencil.noc = mat->stencil.noc;
4421     for (i = 0; i <= mat->stencil.dim; i++) {
4422       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4423       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4424     }
4425     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4426   }
4427   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4428 
4429   /* Copy Mat options */
4430   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4431   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4432   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4433   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4434   PetscFunctionReturn(0);
4435 }
4436 
4437 /*@C
4438    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4439 
4440    Not Collective
4441 
4442    Input Parameter:
4443 .  mat - the matrix, must be a factored matrix
4444 
4445    Output Parameter:
4446 .   type - the string name of the package (do not free this string)
4447 
4448    Level: intermediate
4449 
4450    Fortran Note:
4451    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4452 
4453 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4454 @*/
4455 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4456 {
4457   PetscErrorCode (*conv)(Mat, MatSolverType *);
4458 
4459   PetscFunctionBegin;
4460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4461   PetscValidType(mat, 1);
4462   PetscValidPointer(type, 2);
4463   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4464   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4465   if (conv) PetscCall((*conv)(mat, type));
4466   else *type = MATSOLVERPETSC;
4467   PetscFunctionReturn(0);
4468 }
4469 
4470 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4471 struct _MatSolverTypeForSpecifcType {
4472   MatType mtype;
4473   /* no entry for MAT_FACTOR_NONE */
4474   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4475   MatSolverTypeForSpecifcType next;
4476 };
4477 
4478 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4479 struct _MatSolverTypeHolder {
4480   char                       *name;
4481   MatSolverTypeForSpecifcType handlers;
4482   MatSolverTypeHolder         next;
4483 };
4484 
4485 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4486 
4487 /*@C
4488    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4489 
4490    Input Parameters:
4491 +    package - name of the package, for example petsc or superlu
4492 .    mtype - the matrix type that works with this package
4493 .    ftype - the type of factorization supported by the package
4494 -    createfactor - routine that will create the factored matrix ready to be used
4495 
4496     Level: developer
4497 
4498 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4499 @*/
4500 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4501 {
4502   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4503   PetscBool                   flg;
4504   MatSolverTypeForSpecifcType inext, iprev = NULL;
4505 
4506   PetscFunctionBegin;
4507   PetscCall(MatInitializePackage());
4508   if (!next) {
4509     PetscCall(PetscNew(&MatSolverTypeHolders));
4510     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4511     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4512     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4513     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4514     PetscFunctionReturn(0);
4515   }
4516   while (next) {
4517     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4518     if (flg) {
4519       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4520       inext = next->handlers;
4521       while (inext) {
4522         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4523         if (flg) {
4524           inext->createfactor[(int)ftype - 1] = createfactor;
4525           PetscFunctionReturn(0);
4526         }
4527         iprev = inext;
4528         inext = inext->next;
4529       }
4530       PetscCall(PetscNew(&iprev->next));
4531       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4532       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4533       PetscFunctionReturn(0);
4534     }
4535     prev = next;
4536     next = next->next;
4537   }
4538   PetscCall(PetscNew(&prev->next));
4539   PetscCall(PetscStrallocpy(package, &prev->next->name));
4540   PetscCall(PetscNew(&prev->next->handlers));
4541   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4542   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4543   PetscFunctionReturn(0);
4544 }
4545 
4546 /*@C
4547    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4548 
4549    Input Parameters:
4550 +    type - name of the package, for example petsc or superlu
4551 .    ftype - the type of factorization supported by the type
4552 -    mtype - the matrix type that works with this type
4553 
4554    Output Parameters:
4555 +   foundtype - `PETSC_TRUE` if the type was registered
4556 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4557 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4558 
4559     Level: developer
4560 
4561 .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4562 @*/
4563 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4564 {
4565   MatSolverTypeHolder         next = MatSolverTypeHolders;
4566   PetscBool                   flg;
4567   MatSolverTypeForSpecifcType inext;
4568 
4569   PetscFunctionBegin;
4570   if (foundtype) *foundtype = PETSC_FALSE;
4571   if (foundmtype) *foundmtype = PETSC_FALSE;
4572   if (createfactor) *createfactor = NULL;
4573 
4574   if (type) {
4575     while (next) {
4576       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4577       if (flg) {
4578         if (foundtype) *foundtype = PETSC_TRUE;
4579         inext = next->handlers;
4580         while (inext) {
4581           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4582           if (flg) {
4583             if (foundmtype) *foundmtype = PETSC_TRUE;
4584             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4585             PetscFunctionReturn(0);
4586           }
4587           inext = inext->next;
4588         }
4589       }
4590       next = next->next;
4591     }
4592   } else {
4593     while (next) {
4594       inext = next->handlers;
4595       while (inext) {
4596         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4597         if (flg && inext->createfactor[(int)ftype - 1]) {
4598           if (foundtype) *foundtype = PETSC_TRUE;
4599           if (foundmtype) *foundmtype = PETSC_TRUE;
4600           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4601           PetscFunctionReturn(0);
4602         }
4603         inext = inext->next;
4604       }
4605       next = next->next;
4606     }
4607     /* try with base classes inext->mtype */
4608     next = MatSolverTypeHolders;
4609     while (next) {
4610       inext = next->handlers;
4611       while (inext) {
4612         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4613         if (flg && inext->createfactor[(int)ftype - 1]) {
4614           if (foundtype) *foundtype = PETSC_TRUE;
4615           if (foundmtype) *foundmtype = PETSC_TRUE;
4616           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4617           PetscFunctionReturn(0);
4618         }
4619         inext = inext->next;
4620       }
4621       next = next->next;
4622     }
4623   }
4624   PetscFunctionReturn(0);
4625 }
4626 
4627 PetscErrorCode MatSolverTypeDestroy(void)
4628 {
4629   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4630   MatSolverTypeForSpecifcType inext, iprev;
4631 
4632   PetscFunctionBegin;
4633   while (next) {
4634     PetscCall(PetscFree(next->name));
4635     inext = next->handlers;
4636     while (inext) {
4637       PetscCall(PetscFree(inext->mtype));
4638       iprev = inext;
4639       inext = inext->next;
4640       PetscCall(PetscFree(iprev));
4641     }
4642     prev = next;
4643     next = next->next;
4644     PetscCall(PetscFree(prev));
4645   }
4646   MatSolverTypeHolders = NULL;
4647   PetscFunctionReturn(0);
4648 }
4649 
4650 /*@C
4651    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4652 
4653    Logically Collective
4654 
4655    Input Parameters:
4656 .  mat - the matrix
4657 
4658    Output Parameters:
4659 .  flg - `PETSC_TRUE` if uses the ordering
4660 
4661    Level: developer
4662 
4663    Note:
4664    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4665    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4666 
4667 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4668 @*/
4669 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4670 {
4671   PetscFunctionBegin;
4672   *flg = mat->canuseordering;
4673   PetscFunctionReturn(0);
4674 }
4675 
4676 /*@C
4677    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4678 
4679    Logically Collective
4680 
4681    Input Parameters:
4682 .  mat - the matrix obtained with `MatGetFactor()`
4683 
4684    Output Parameters:
4685 .  otype - the preferred type
4686 
4687    Level: developer
4688 
4689 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4690 @*/
4691 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4692 {
4693   PetscFunctionBegin;
4694   *otype = mat->preferredordering[ftype];
4695   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4696   PetscFunctionReturn(0);
4697 }
4698 
4699 /*@C
4700    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4701 
4702    Collective
4703 
4704    Input Parameters:
4705 +  mat - the matrix
4706 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4707 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4708 
4709    Output Parameters:
4710 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4711 
4712    Options Database Key:
4713 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4714                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4715 
4716    Level: intermediate
4717 
4718    Notes:
4719      Users usually access the factorization solvers via `KSP`
4720 
4721       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4722      such as pastix, superlu, mumps etc.
4723 
4724       PETSc must have been ./configure to use the external solver, using the option --download-package
4725 
4726       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4727       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4728       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4729 
4730    Developer Note:
4731       This should actually be called `MatCreateFactor()` since it creates a new factor object
4732 
4733 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4734           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4735 @*/
4736 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4737 {
4738   PetscBool foundtype, foundmtype;
4739   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4740 
4741   PetscFunctionBegin;
4742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4743   PetscValidType(mat, 1);
4744 
4745   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4746   MatCheckPreallocated(mat, 1);
4747 
4748   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4749   if (!foundtype) {
4750     if (type) {
4751       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],
4752               ((PetscObject)mat)->type_name, type);
4753     } else {
4754       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);
4755     }
4756   }
4757   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4758   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);
4759 
4760   PetscCall((*conv)(mat, ftype, f));
4761   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4762   PetscFunctionReturn(0);
4763 }
4764 
4765 /*@C
4766    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4767 
4768    Not Collective
4769 
4770    Input Parameters:
4771 +  mat - the matrix
4772 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4773 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4774 
4775    Output Parameter:
4776 .    flg - PETSC_TRUE if the factorization is available
4777 
4778    Level: intermediate
4779 
4780    Notes:
4781       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4782      such as pastix, superlu, mumps etc.
4783 
4784       PETSc must have been ./configure to use the external solver, using the option --download-package
4785 
4786    Developer Note:
4787       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4788 
4789 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4790           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4791 @*/
4792 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4793 {
4794   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4795 
4796   PetscFunctionBegin;
4797   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4798   PetscValidType(mat, 1);
4799   PetscValidBoolPointer(flg, 4);
4800 
4801   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4802   MatCheckPreallocated(mat, 1);
4803 
4804   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4805   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4806   PetscFunctionReturn(0);
4807 }
4808 
4809 /*@
4810    MatDuplicate - Duplicates a matrix including the non-zero structure.
4811 
4812    Collective
4813 
4814    Input Parameters:
4815 +  mat - the matrix
4816 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4817         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4818 
4819    Output Parameter:
4820 .  M - pointer to place new matrix
4821 
4822    Level: intermediate
4823 
4824    Notes:
4825     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4826 
4827     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.
4828 
4829     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
4830     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4831     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4832 
4833 .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4834 @*/
4835 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4836 {
4837   Mat         B;
4838   VecType     vtype;
4839   PetscInt    i;
4840   PetscObject dm;
4841   void (*viewf)(void);
4842 
4843   PetscFunctionBegin;
4844   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4845   PetscValidType(mat, 1);
4846   PetscValidPointer(M, 3);
4847   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4848   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4849   MatCheckPreallocated(mat, 1);
4850 
4851   *M = NULL;
4852   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4853   PetscUseTypeMethod(mat, duplicate, op, M);
4854   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4855   B = *M;
4856 
4857   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4858   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4859   PetscCall(MatGetVecType(mat, &vtype));
4860   PetscCall(MatSetVecType(B, vtype));
4861 
4862   B->stencil.dim = mat->stencil.dim;
4863   B->stencil.noc = mat->stencil.noc;
4864   for (i = 0; i <= mat->stencil.dim; i++) {
4865     B->stencil.dims[i]   = mat->stencil.dims[i];
4866     B->stencil.starts[i] = mat->stencil.starts[i];
4867   }
4868 
4869   B->nooffproczerorows = mat->nooffproczerorows;
4870   B->nooffprocentries  = mat->nooffprocentries;
4871 
4872   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4873   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4874   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4875   PetscFunctionReturn(0);
4876 }
4877 
4878 /*@
4879    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4880 
4881    Logically Collective
4882 
4883    Input Parameters:
4884 +  mat - the matrix
4885 -  v - the vector for storing the diagonal
4886 
4887    Output Parameter:
4888 .  v - the diagonal of the matrix
4889 
4890    Level: intermediate
4891 
4892    Note:
4893    Currently only correct in parallel for square matrices.
4894 
4895 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4896 @*/
4897 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4898 {
4899   PetscFunctionBegin;
4900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4901   PetscValidType(mat, 1);
4902   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4903   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4904   MatCheckPreallocated(mat, 1);
4905 
4906   PetscUseTypeMethod(mat, getdiagonal, v);
4907   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4908   PetscFunctionReturn(0);
4909 }
4910 
4911 /*@C
4912    MatGetRowMin - Gets the minimum value (of the real part) of each
4913         row of the matrix
4914 
4915    Logically Collective
4916 
4917    Input Parameter:
4918 .  mat - the matrix
4919 
4920    Output Parameters:
4921 +  v - the vector for storing the maximums
4922 -  idx - the indices of the column found for each row (optional)
4923 
4924    Level: intermediate
4925 
4926    Note:
4927     The result of this call are the same as if one converted the matrix to dense format
4928       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4929 
4930     This code is only implemented for a couple of matrix formats.
4931 
4932 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4933           `MatGetRowMax()`
4934 @*/
4935 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4936 {
4937   PetscFunctionBegin;
4938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4939   PetscValidType(mat, 1);
4940   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4941   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4942 
4943   if (!mat->cmap->N) {
4944     PetscCall(VecSet(v, PETSC_MAX_REAL));
4945     if (idx) {
4946       PetscInt i, m = mat->rmap->n;
4947       for (i = 0; i < m; i++) idx[i] = -1;
4948     }
4949   } else {
4950     MatCheckPreallocated(mat, 1);
4951   }
4952   PetscUseTypeMethod(mat, getrowmin, v, idx);
4953   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4954   PetscFunctionReturn(0);
4955 }
4956 
4957 /*@C
4958    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4959         row of the matrix
4960 
4961    Logically Collective
4962 
4963    Input Parameter:
4964 .  mat - the matrix
4965 
4966    Output Parameters:
4967 +  v - the vector for storing the minimums
4968 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4969 
4970    Level: intermediate
4971 
4972    Notes:
4973     if a row is completely empty or has only 0.0 values then the idx[] value for that
4974     row is 0 (the first column).
4975 
4976     This code is only implemented for a couple of matrix formats.
4977 
4978 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4979 @*/
4980 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4981 {
4982   PetscFunctionBegin;
4983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4984   PetscValidType(mat, 1);
4985   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4986   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4987   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4988 
4989   if (!mat->cmap->N) {
4990     PetscCall(VecSet(v, 0.0));
4991     if (idx) {
4992       PetscInt i, m = mat->rmap->n;
4993       for (i = 0; i < m; i++) idx[i] = -1;
4994     }
4995   } else {
4996     MatCheckPreallocated(mat, 1);
4997     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4998     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4999   }
5000   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5001   PetscFunctionReturn(0);
5002 }
5003 
5004 /*@C
5005    MatGetRowMax - Gets the maximum value (of the real part) of each
5006         row of the matrix
5007 
5008    Logically Collective
5009 
5010    Input Parameter:
5011 .  mat - the matrix
5012 
5013    Output Parameters:
5014 +  v - the vector for storing the maximums
5015 -  idx - the indices of the column found for each row (optional)
5016 
5017    Level: intermediate
5018 
5019    Notes:
5020     The result of this call are the same as if one converted the matrix to dense format
5021       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5022 
5023     This code is only implemented for a couple of matrix formats.
5024 
5025 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5026 @*/
5027 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5028 {
5029   PetscFunctionBegin;
5030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5031   PetscValidType(mat, 1);
5032   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5033   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5034 
5035   if (!mat->cmap->N) {
5036     PetscCall(VecSet(v, PETSC_MIN_REAL));
5037     if (idx) {
5038       PetscInt i, m = mat->rmap->n;
5039       for (i = 0; i < m; i++) idx[i] = -1;
5040     }
5041   } else {
5042     MatCheckPreallocated(mat, 1);
5043     PetscUseTypeMethod(mat, getrowmax, v, idx);
5044   }
5045   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5046   PetscFunctionReturn(0);
5047 }
5048 
5049 /*@C
5050    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5051         row of the matrix
5052 
5053    Logically Collective
5054 
5055    Input Parameter:
5056 .  mat - the matrix
5057 
5058    Output Parameters:
5059 +  v - the vector for storing the maximums
5060 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5061 
5062    Level: intermediate
5063 
5064    Notes:
5065     if a row is completely empty or has only 0.0 values then the idx[] value for that
5066     row is 0 (the first column).
5067 
5068     This code is only implemented for a couple of matrix formats.
5069 
5070 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5071 @*/
5072 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5073 {
5074   PetscFunctionBegin;
5075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5076   PetscValidType(mat, 1);
5077   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5078   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5079 
5080   if (!mat->cmap->N) {
5081     PetscCall(VecSet(v, 0.0));
5082     if (idx) {
5083       PetscInt i, m = mat->rmap->n;
5084       for (i = 0; i < m; i++) idx[i] = -1;
5085     }
5086   } else {
5087     MatCheckPreallocated(mat, 1);
5088     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5089     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5090   }
5091   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5092   PetscFunctionReturn(0);
5093 }
5094 
5095 /*@
5096    MatGetRowSum - Gets the sum of each row of the matrix
5097 
5098    Logically or Neighborhood Collective
5099 
5100    Input Parameters:
5101 .  mat - the matrix
5102 
5103    Output Parameter:
5104 .  v - the vector for storing the sum of rows
5105 
5106    Level: intermediate
5107 
5108    Notes:
5109     This code is slow since it is not currently specialized for different formats
5110 
5111 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5112 @*/
5113 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5114 {
5115   Vec ones;
5116 
5117   PetscFunctionBegin;
5118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5119   PetscValidType(mat, 1);
5120   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5121   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5122   MatCheckPreallocated(mat, 1);
5123   PetscCall(MatCreateVecs(mat, &ones, NULL));
5124   PetscCall(VecSet(ones, 1.));
5125   PetscCall(MatMult(mat, ones, v));
5126   PetscCall(VecDestroy(&ones));
5127   PetscFunctionReturn(0);
5128 }
5129 
5130 /*@
5131    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5132    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5133 
5134    Collective
5135 
5136    Input Parameter:
5137 .  mat - the matrix to provide the transpose
5138 
5139    Output Parameter:
5140 .  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
5141 
5142    Level: advanced
5143 
5144    Note:
5145    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
5146    routine allows bypassing that call.
5147 
5148 .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5149 @*/
5150 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5151 {
5152   PetscContainer  rB = NULL;
5153   MatParentState *rb = NULL;
5154 
5155   PetscFunctionBegin;
5156   PetscCall(PetscNew(&rb));
5157   rb->id    = ((PetscObject)mat)->id;
5158   rb->state = 0;
5159   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5160   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5161   PetscCall(PetscContainerSetPointer(rB, rb));
5162   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5163   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5164   PetscCall(PetscObjectDereference((PetscObject)rB));
5165   PetscFunctionReturn(0);
5166 }
5167 
5168 /*@
5169    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5170 
5171    Collective
5172 
5173    Input Parameters:
5174 +  mat - the matrix to transpose
5175 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5176 
5177    Output Parameter:
5178 .  B - the transpose
5179 
5180    Level: intermediate
5181 
5182    Notes:
5183      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5184 
5185      `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
5186      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5187 
5188      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.
5189 
5190      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5191 
5192      If mat is unchanged from the last call this function returns immediately without recomputing the result
5193 
5194      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5195 
5196 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5197           `MatTransposeSymbolic()`
5198 @*/
5199 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5200 {
5201   PetscContainer  rB = NULL;
5202   MatParentState *rb = NULL;
5203 
5204   PetscFunctionBegin;
5205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5206   PetscValidType(mat, 1);
5207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5208   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5209   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5210   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5211   MatCheckPreallocated(mat, 1);
5212   if (reuse == MAT_REUSE_MATRIX) {
5213     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5214     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5215     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5216     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5217     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5218   }
5219 
5220   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5221   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5222     PetscUseTypeMethod(mat, transpose, reuse, B);
5223     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5224   }
5225   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5226 
5227   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5228   if (reuse != MAT_INPLACE_MATRIX) {
5229     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5230     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5231     rb->state        = ((PetscObject)mat)->state;
5232     rb->nonzerostate = mat->nonzerostate;
5233   }
5234   PetscFunctionReturn(0);
5235 }
5236 
5237 /*@
5238    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5239 
5240    Collective
5241 
5242    Input Parameters:
5243 .  A - the matrix to transpose
5244 
5245    Output Parameter:
5246 .  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
5247       numerical portion.
5248 
5249    Level: intermediate
5250 
5251    Note:
5252    This is not supported for many matrix types, use `MatTranspose()` in those cases
5253 
5254 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5255 @*/
5256 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5257 {
5258   PetscFunctionBegin;
5259   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5260   PetscValidType(A, 1);
5261   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5262   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5263   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5264   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5265   PetscCall((*A->ops->transposesymbolic)(A, B));
5266   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5267 
5268   PetscCall(MatTransposeSetPrecursor(A, *B));
5269   PetscFunctionReturn(0);
5270 }
5271 
5272 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5273 {
5274   PetscContainer  rB;
5275   MatParentState *rb;
5276 
5277   PetscFunctionBegin;
5278   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5279   PetscValidType(A, 1);
5280   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5281   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5282   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5283   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5284   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5285   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5286   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5287   PetscFunctionReturn(0);
5288 }
5289 
5290 /*@
5291    MatIsTranspose - Test whether a matrix is another one's transpose,
5292         or its own, in which case it tests symmetry.
5293 
5294    Collective
5295 
5296    Input Parameters:
5297 +  A - the matrix to test
5298 -  B - the matrix to test against, this can equal the first parameter
5299 
5300    Output Parameters:
5301 .  flg - the result
5302 
5303    Level: intermediate
5304 
5305    Notes:
5306    Only available for `MATAIJ` matrices.
5307 
5308    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5309    test involves parallel copies of the block-offdiagonal parts of the matrix.
5310 
5311 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5312 @*/
5313 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5314 {
5315   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5316 
5317   PetscFunctionBegin;
5318   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5319   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5320   PetscValidBoolPointer(flg, 4);
5321   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5322   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5323   *flg = PETSC_FALSE;
5324   if (f && g) {
5325     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5326     PetscCall((*f)(A, B, tol, flg));
5327   } else {
5328     MatType mattype;
5329 
5330     PetscCall(MatGetType(f ? B : A, &mattype));
5331     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5332   }
5333   PetscFunctionReturn(0);
5334 }
5335 
5336 /*@
5337    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5338 
5339    Collective
5340 
5341    Input Parameters:
5342 +  mat - the matrix to transpose and complex conjugate
5343 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5344 
5345    Output Parameter:
5346 .  B - the Hermitian transpose
5347 
5348    Level: intermediate
5349 
5350 .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5351 @*/
5352 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5353 {
5354   PetscFunctionBegin;
5355   PetscCall(MatTranspose(mat, reuse, B));
5356 #if defined(PETSC_USE_COMPLEX)
5357   PetscCall(MatConjugate(*B));
5358 #endif
5359   PetscFunctionReturn(0);
5360 }
5361 
5362 /*@
5363    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5364 
5365    Collective
5366 
5367    Input Parameters:
5368 +  A - the matrix to test
5369 -  B - the matrix to test against, this can equal the first parameter
5370 
5371    Output Parameters:
5372 .  flg - the result
5373 
5374    Level: intermediate
5375 
5376    Notes:
5377    Only available for `MATAIJ` matrices.
5378 
5379    The sequential algorithm
5380    has a running time of the order of the number of nonzeros; the parallel
5381    test involves parallel copies of the block-offdiagonal parts of the matrix.
5382 
5383 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5384 @*/
5385 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5386 {
5387   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5388 
5389   PetscFunctionBegin;
5390   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5391   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5392   PetscValidBoolPointer(flg, 4);
5393   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5394   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5395   if (f && g) {
5396     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5397     PetscCall((*f)(A, B, tol, flg));
5398   }
5399   PetscFunctionReturn(0);
5400 }
5401 
5402 /*@
5403    MatPermute - Creates a new matrix with rows and columns permuted from the
5404    original.
5405 
5406    Collective
5407 
5408    Input Parameters:
5409 +  mat - the matrix to permute
5410 .  row - row permutation, each processor supplies only the permutation for its rows
5411 -  col - column permutation, each processor supplies only the permutation for its columns
5412 
5413    Output Parameters:
5414 .  B - the permuted matrix
5415 
5416    Level: advanced
5417 
5418    Note:
5419    The index sets map from row/col of permuted matrix to row/col of original matrix.
5420    The index sets should be on the same communicator as mat and have the same local sizes.
5421 
5422    Developer Note:
5423      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5424      exploit the fact that row and col are permutations, consider implementing the
5425      more general `MatCreateSubMatrix()` instead.
5426 
5427 .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5428 @*/
5429 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5430 {
5431   PetscFunctionBegin;
5432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5433   PetscValidType(mat, 1);
5434   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5435   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5436   PetscValidPointer(B, 4);
5437   PetscCheckSameComm(mat, 1, row, 2);
5438   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5439   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5440   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5441   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5442   MatCheckPreallocated(mat, 1);
5443 
5444   if (mat->ops->permute) {
5445     PetscUseTypeMethod(mat, permute, row, col, B);
5446     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5447   } else {
5448     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5449   }
5450   PetscFunctionReturn(0);
5451 }
5452 
5453 /*@
5454    MatEqual - Compares two matrices.
5455 
5456    Collective
5457 
5458    Input Parameters:
5459 +  A - the first matrix
5460 -  B - the second matrix
5461 
5462    Output Parameter:
5463 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5464 
5465    Level: intermediate
5466 
5467 .seealso: `Mat`
5468 @*/
5469 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5470 {
5471   PetscFunctionBegin;
5472   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5473   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5474   PetscValidType(A, 1);
5475   PetscValidType(B, 2);
5476   PetscValidBoolPointer(flg, 3);
5477   PetscCheckSameComm(A, 1, B, 2);
5478   MatCheckPreallocated(A, 1);
5479   MatCheckPreallocated(B, 2);
5480   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5481   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5482   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,
5483              B->cmap->N);
5484   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5485     PetscUseTypeMethod(A, equal, B, flg);
5486   } else {
5487     PetscCall(MatMultEqual(A, B, 10, flg));
5488   }
5489   PetscFunctionReturn(0);
5490 }
5491 
5492 /*@
5493    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5494    matrices that are stored as vectors.  Either of the two scaling
5495    matrices can be `NULL`.
5496 
5497    Collective
5498 
5499    Input Parameters:
5500 +  mat - the matrix to be scaled
5501 .  l - the left scaling vector (or `NULL`)
5502 -  r - the right scaling vector (or `NULL`)
5503 
5504    Level: intermediate
5505 
5506    Note:
5507    `MatDiagonalScale()` computes A = LAR, where
5508    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5509    The L scales the rows of the matrix, the R scales the columns of the matrix.
5510 
5511 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5512 @*/
5513 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5514 {
5515   PetscFunctionBegin;
5516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5517   PetscValidType(mat, 1);
5518   if (l) {
5519     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5520     PetscCheckSameComm(mat, 1, l, 2);
5521   }
5522   if (r) {
5523     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5524     PetscCheckSameComm(mat, 1, r, 3);
5525   }
5526   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5527   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5528   MatCheckPreallocated(mat, 1);
5529   if (!l && !r) PetscFunctionReturn(0);
5530 
5531   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5532   PetscUseTypeMethod(mat, diagonalscale, l, r);
5533   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5534   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5535   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5536   PetscFunctionReturn(0);
5537 }
5538 
5539 /*@
5540     MatScale - Scales all elements of a matrix by a given number.
5541 
5542     Logically Collective
5543 
5544     Input Parameters:
5545 +   mat - the matrix to be scaled
5546 -   a  - the scaling value
5547 
5548     Output Parameter:
5549 .   mat - the scaled matrix
5550 
5551     Level: intermediate
5552 
5553 .seealso: `Mat`, `MatDiagonalScale()`
5554 @*/
5555 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5556 {
5557   PetscFunctionBegin;
5558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5559   PetscValidType(mat, 1);
5560   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5561   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5562   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5563   PetscValidLogicalCollectiveScalar(mat, a, 2);
5564   MatCheckPreallocated(mat, 1);
5565 
5566   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5567   if (a != (PetscScalar)1.0) {
5568     PetscUseTypeMethod(mat, scale, a);
5569     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5570   }
5571   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5572   PetscFunctionReturn(0);
5573 }
5574 
5575 /*@
5576    MatNorm - Calculates various norms of a matrix.
5577 
5578    Collective
5579 
5580    Input Parameters:
5581 +  mat - the matrix
5582 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5583 
5584    Output Parameter:
5585 .  nrm - the resulting norm
5586 
5587    Level: intermediate
5588 
5589 .seealso: `Mat`
5590 @*/
5591 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5592 {
5593   PetscFunctionBegin;
5594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5595   PetscValidType(mat, 1);
5596   PetscValidRealPointer(nrm, 3);
5597 
5598   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5599   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5600   MatCheckPreallocated(mat, 1);
5601 
5602   PetscUseTypeMethod(mat, norm, type, nrm);
5603   PetscFunctionReturn(0);
5604 }
5605 
5606 /*
5607      This variable is used to prevent counting of MatAssemblyBegin() that
5608    are called from within a MatAssemblyEnd().
5609 */
5610 static PetscInt MatAssemblyEnd_InUse = 0;
5611 /*@
5612    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5613    be called after completing all calls to `MatSetValues()`.
5614 
5615    Collective
5616 
5617    Input Parameters:
5618 +  mat - the matrix
5619 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5620 
5621    Level: beginner
5622 
5623    Notes:
5624    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5625    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5626 
5627    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5628    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5629    using the matrix.
5630 
5631    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5632    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
5633    a global collective operation requiring all processes that share the matrix.
5634 
5635    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5636    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5637    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5638 
5639 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5640 @*/
5641 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5642 {
5643   PetscFunctionBegin;
5644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5645   PetscValidType(mat, 1);
5646   MatCheckPreallocated(mat, 1);
5647   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5648   if (mat->assembled) {
5649     mat->was_assembled = PETSC_TRUE;
5650     mat->assembled     = PETSC_FALSE;
5651   }
5652 
5653   if (!MatAssemblyEnd_InUse) {
5654     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5655     PetscTryTypeMethod(mat, assemblybegin, type);
5656     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5657   } else PetscTryTypeMethod(mat, assemblybegin, type);
5658   PetscFunctionReturn(0);
5659 }
5660 
5661 /*@
5662    MatAssembled - Indicates if a matrix has been assembled and is ready for
5663      use; for example, in matrix-vector product.
5664 
5665    Not Collective
5666 
5667    Input Parameter:
5668 .  mat - the matrix
5669 
5670    Output Parameter:
5671 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5672 
5673    Level: advanced
5674 
5675 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5676 @*/
5677 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5678 {
5679   PetscFunctionBegin;
5680   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5681   PetscValidBoolPointer(assembled, 2);
5682   *assembled = mat->assembled;
5683   PetscFunctionReturn(0);
5684 }
5685 
5686 /*@
5687    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5688    be called after `MatAssemblyBegin()`.
5689 
5690    Collective on Mat
5691 
5692    Input Parameters:
5693 +  mat - the matrix
5694 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5695 
5696    Options Database Keys:
5697 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5698 .  -mat_view ::ascii_info_detail - Prints more detailed info
5699 .  -mat_view - Prints matrix in ASCII format
5700 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5701 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5702 .  -display <name> - Sets display name (default is host)
5703 .  -draw_pause <sec> - Sets number of seconds to pause after display
5704 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5705 .  -viewer_socket_machine <machine> - Machine to use for socket
5706 .  -viewer_socket_port <port> - Port number to use for socket
5707 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5708 
5709    Level: beginner
5710 
5711 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5712 @*/
5713 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5714 {
5715   static PetscInt inassm = 0;
5716   PetscBool       flg    = PETSC_FALSE;
5717 
5718   PetscFunctionBegin;
5719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5720   PetscValidType(mat, 1);
5721 
5722   inassm++;
5723   MatAssemblyEnd_InUse++;
5724   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5725     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5726     PetscTryTypeMethod(mat, assemblyend, type);
5727     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5728   } else PetscTryTypeMethod(mat, assemblyend, type);
5729 
5730   /* Flush assembly is not a true assembly */
5731   if (type != MAT_FLUSH_ASSEMBLY) {
5732     if (mat->num_ass) {
5733       if (!mat->symmetry_eternal) {
5734         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5735         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5736       }
5737       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5738       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5739     }
5740     mat->num_ass++;
5741     mat->assembled        = PETSC_TRUE;
5742     mat->ass_nonzerostate = mat->nonzerostate;
5743   }
5744 
5745   mat->insertmode = NOT_SET_VALUES;
5746   MatAssemblyEnd_InUse--;
5747   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5748   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5749     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5750 
5751     if (mat->checksymmetryonassembly) {
5752       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5753       if (flg) {
5754         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5755       } else {
5756         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5757       }
5758     }
5759     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5760   }
5761   inassm--;
5762   PetscFunctionReturn(0);
5763 }
5764 
5765 /*@
5766    MatSetOption - Sets a parameter option for a matrix. Some options
5767    may be specific to certain storage formats.  Some options
5768    determine how values will be inserted (or added). Sorted,
5769    row-oriented input will generally assemble the fastest. The default
5770    is row-oriented.
5771 
5772    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5773 
5774    Input Parameters:
5775 +  mat - the matrix
5776 .  option - the option, one of those listed below (and possibly others),
5777 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5778 
5779   Options Describing Matrix Structure:
5780 +    `MAT_SPD` - symmetric positive definite
5781 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5782 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5783 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5784 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5785 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5786 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5787 
5788    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5789    do not need to be computed (usually at a high cost)
5790 
5791    Options For Use with `MatSetValues()`:
5792    Insert a logically dense subblock, which can be
5793 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5794 
5795    Note these options reflect the data you pass in with `MatSetValues()`; it has
5796    nothing to do with how the data is stored internally in the matrix
5797    data structure.
5798 
5799    When (re)assembling a matrix, we can restrict the input for
5800    efficiency/debugging purposes.  These options include
5801 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5802 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5803 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5804 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5805 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5806 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5807         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5808         performance for very large process counts.
5809 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5810         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5811         functions, instead sending only neighbor messages.
5812 
5813    Level: intermediate
5814 
5815    Notes:
5816    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5817 
5818    Some options are relevant only for particular matrix types and
5819    are thus ignored by others.  Other options are not supported by
5820    certain matrix types and will generate an error message if set.
5821 
5822    If using Fortran to compute a matrix, one may need to
5823    use the column-oriented option (or convert to the row-oriented
5824    format).
5825 
5826    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5827    that would generate a new entry in the nonzero structure is instead
5828    ignored.  Thus, if memory has not already been allocated for this particular
5829    data, then the insertion is ignored. For dense matrices, in which
5830    the entire array is allocated, no entries are ever ignored.
5831    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5832 
5833    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5834    that would generate a new entry in the nonzero structure instead produces
5835    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
5836 
5837    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5838    that would generate a new entry that has not been preallocated will
5839    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5840    only.) This is a useful flag when debugging matrix memory preallocation.
5841    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5842 
5843    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5844    other processors should be dropped, rather than stashed.
5845    This is useful if you know that the "owning" processor is also
5846    always generating the correct matrix entries, so that PETSc need
5847    not transfer duplicate entries generated on another processor.
5848 
5849    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5850    searches during matrix assembly. When this flag is set, the hash table
5851    is created during the first matrix assembly. This hash table is
5852    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5853    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5854    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5855    supported by `MATMPIBAIJ` format only.
5856 
5857    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5858    are kept in the nonzero structure
5859 
5860    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5861    a zero location in the matrix
5862 
5863    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5864 
5865    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5866         zero row routines and thus improves performance for very large process counts.
5867 
5868    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5869         part of the matrix (since they should match the upper triangular part).
5870 
5871    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5872                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5873                      with finite difference schemes with non-periodic boundary conditions.
5874 
5875    Developer Note:
5876    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5877    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5878    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5879    not changed.
5880 
5881 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5882 @*/
5883 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5884 {
5885   PetscFunctionBegin;
5886   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5887   if (op > 0) {
5888     PetscValidLogicalCollectiveEnum(mat, op, 2);
5889     PetscValidLogicalCollectiveBool(mat, flg, 3);
5890   }
5891 
5892   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);
5893 
5894   switch (op) {
5895   case MAT_FORCE_DIAGONAL_ENTRIES:
5896     mat->force_diagonals = flg;
5897     PetscFunctionReturn(0);
5898   case MAT_NO_OFF_PROC_ENTRIES:
5899     mat->nooffprocentries = flg;
5900     PetscFunctionReturn(0);
5901   case MAT_SUBSET_OFF_PROC_ENTRIES:
5902     mat->assembly_subset = flg;
5903     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5904 #if !defined(PETSC_HAVE_MPIUNI)
5905       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5906 #endif
5907       mat->stash.first_assembly_done = PETSC_FALSE;
5908     }
5909     PetscFunctionReturn(0);
5910   case MAT_NO_OFF_PROC_ZERO_ROWS:
5911     mat->nooffproczerorows = flg;
5912     PetscFunctionReturn(0);
5913   case MAT_SPD:
5914     if (flg) {
5915       mat->spd                    = PETSC_BOOL3_TRUE;
5916       mat->symmetric              = PETSC_BOOL3_TRUE;
5917       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5918     } else {
5919       mat->spd = PETSC_BOOL3_FALSE;
5920     }
5921     break;
5922   case MAT_SYMMETRIC:
5923     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5924     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5925 #if !defined(PETSC_USE_COMPLEX)
5926     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5927 #endif
5928     break;
5929   case MAT_HERMITIAN:
5930     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5931     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5932 #if !defined(PETSC_USE_COMPLEX)
5933     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5934 #endif
5935     break;
5936   case MAT_STRUCTURALLY_SYMMETRIC:
5937     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5938     break;
5939   case MAT_SYMMETRY_ETERNAL:
5940     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");
5941     mat->symmetry_eternal = flg;
5942     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5943     break;
5944   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5945     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");
5946     mat->structural_symmetry_eternal = flg;
5947     break;
5948   case MAT_SPD_ETERNAL:
5949     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");
5950     mat->spd_eternal = flg;
5951     if (flg) {
5952       mat->structural_symmetry_eternal = PETSC_TRUE;
5953       mat->symmetry_eternal            = PETSC_TRUE;
5954     }
5955     break;
5956   case MAT_STRUCTURE_ONLY:
5957     mat->structure_only = flg;
5958     break;
5959   case MAT_SORTED_FULL:
5960     mat->sortedfull = flg;
5961     break;
5962   default:
5963     break;
5964   }
5965   PetscTryTypeMethod(mat, setoption, op, flg);
5966   PetscFunctionReturn(0);
5967 }
5968 
5969 /*@
5970    MatGetOption - Gets a parameter option that has been set for a matrix.
5971 
5972    Logically Collective
5973 
5974    Input Parameters:
5975 +  mat - the matrix
5976 -  option - the option, this only responds to certain options, check the code for which ones
5977 
5978    Output Parameter:
5979 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5980 
5981    Level: intermediate
5982 
5983     Notes:
5984     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5985 
5986     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5987     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5988 
5989 .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5990     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5991 @*/
5992 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5993 {
5994   PetscFunctionBegin;
5995   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5996   PetscValidType(mat, 1);
5997 
5998   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);
5999   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()");
6000 
6001   switch (op) {
6002   case MAT_NO_OFF_PROC_ENTRIES:
6003     *flg = mat->nooffprocentries;
6004     break;
6005   case MAT_NO_OFF_PROC_ZERO_ROWS:
6006     *flg = mat->nooffproczerorows;
6007     break;
6008   case MAT_SYMMETRIC:
6009     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6010     break;
6011   case MAT_HERMITIAN:
6012     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6013     break;
6014   case MAT_STRUCTURALLY_SYMMETRIC:
6015     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6016     break;
6017   case MAT_SPD:
6018     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6019     break;
6020   case MAT_SYMMETRY_ETERNAL:
6021     *flg = mat->symmetry_eternal;
6022     break;
6023   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6024     *flg = mat->symmetry_eternal;
6025     break;
6026   default:
6027     break;
6028   }
6029   PetscFunctionReturn(0);
6030 }
6031 
6032 /*@
6033    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6034    this routine retains the old nonzero structure.
6035 
6036    Logically Collective
6037 
6038    Input Parameters:
6039 .  mat - the matrix
6040 
6041    Level: intermediate
6042 
6043    Note:
6044     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.
6045    See the Performance chapter of the users manual for information on preallocating matrices.
6046 
6047 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6048 @*/
6049 PetscErrorCode MatZeroEntries(Mat mat)
6050 {
6051   PetscFunctionBegin;
6052   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6053   PetscValidType(mat, 1);
6054   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6055   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");
6056   MatCheckPreallocated(mat, 1);
6057 
6058   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6059   PetscUseTypeMethod(mat, zeroentries);
6060   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6061   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6062   PetscFunctionReturn(0);
6063 }
6064 
6065 /*@
6066    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6067    of a set of rows and columns of a matrix.
6068 
6069    Collective
6070 
6071    Input Parameters:
6072 +  mat - the matrix
6073 .  numRows - the number of rows/columns to zero
6074 .  rows - the global row indices
6075 .  diag - value put in the diagonal of the eliminated rows
6076 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6077 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6078 
6079    Level: intermediate
6080 
6081    Notes:
6082    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6083 
6084    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6085    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
6086 
6087    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6088    Krylov method to take advantage of the known solution on the zeroed rows.
6089 
6090    For the parallel case, all processes that share the matrix (i.e.,
6091    those in the communicator used for matrix creation) MUST call this
6092    routine, regardless of whether any rows being zeroed are owned by
6093    them.
6094 
6095    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6096 
6097    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6098    list only rows local to itself).
6099 
6100    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6101 
6102 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6103           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6104 @*/
6105 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6106 {
6107   PetscFunctionBegin;
6108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6109   PetscValidType(mat, 1);
6110   if (numRows) PetscValidIntPointer(rows, 3);
6111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6112   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6113   MatCheckPreallocated(mat, 1);
6114 
6115   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6116   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6117   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6118   PetscFunctionReturn(0);
6119 }
6120 
6121 /*@
6122    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6123    of a set of rows and columns of a matrix.
6124 
6125    Collective
6126 
6127    Input Parameters:
6128 +  mat - the matrix
6129 .  is - the rows to zero
6130 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6131 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6132 -  b - optional vector of right hand side, that will be adjusted by provided solution
6133 
6134    Level: intermediate
6135 
6136    Note:
6137    See `MatZeroRowsColumns()` for details on how this routine operates.
6138 
6139 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6140           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6141 @*/
6142 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6143 {
6144   PetscInt        numRows;
6145   const PetscInt *rows;
6146 
6147   PetscFunctionBegin;
6148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6149   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6150   PetscValidType(mat, 1);
6151   PetscValidType(is, 2);
6152   PetscCall(ISGetLocalSize(is, &numRows));
6153   PetscCall(ISGetIndices(is, &rows));
6154   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6155   PetscCall(ISRestoreIndices(is, &rows));
6156   PetscFunctionReturn(0);
6157 }
6158 
6159 /*@
6160    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6161    of a set of rows of a matrix.
6162 
6163    Collective
6164 
6165    Input Parameters:
6166 +  mat - the matrix
6167 .  numRows - the number of rows to zero
6168 .  rows - the global row indices
6169 .  diag - value put in the diagonal of the zeroed rows
6170 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6171 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6172 
6173    Level: intermediate
6174 
6175    Notes:
6176    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6177 
6178    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6179 
6180    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6181    Krylov method to take advantage of the known solution on the zeroed rows.
6182 
6183    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6184    from the matrix.
6185 
6186    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6187    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
6188    formats this does not alter the nonzero structure.
6189 
6190    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6191    of the matrix is not changed the values are
6192    merely zeroed.
6193 
6194    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6195    formats can optionally remove the main diagonal entry from the
6196    nonzero structure as well, by passing 0.0 as the final argument).
6197 
6198    For the parallel case, all processes that share the matrix (i.e.,
6199    those in the communicator used for matrix creation) MUST call this
6200    routine, regardless of whether any rows being zeroed are owned by
6201    them.
6202 
6203    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6204    list only rows local to itself).
6205 
6206    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6207    owns that are to be zeroed. This saves a global synchronization in the implementation.
6208 
6209 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6210           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6211 @*/
6212 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6213 {
6214   PetscFunctionBegin;
6215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6216   PetscValidType(mat, 1);
6217   if (numRows) PetscValidIntPointer(rows, 3);
6218   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6219   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6220   MatCheckPreallocated(mat, 1);
6221 
6222   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6223   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6224   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6225   PetscFunctionReturn(0);
6226 }
6227 
6228 /*@
6229    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6230    of a set of rows of a matrix.
6231 
6232    Collective on Mat
6233 
6234    Input Parameters:
6235 +  mat - the matrix
6236 .  is - index set of rows to remove (if `NULL` then no row is removed)
6237 .  diag - value put in all diagonals of eliminated rows
6238 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6239 -  b - optional vector of right hand side, that will be adjusted by provided solution
6240 
6241    Level: intermediate
6242 
6243    Note:
6244    See `MatZeroRows()` for details on how this routine operates.
6245 
6246 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6247           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6248 @*/
6249 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6250 {
6251   PetscInt        numRows = 0;
6252   const PetscInt *rows    = NULL;
6253 
6254   PetscFunctionBegin;
6255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6256   PetscValidType(mat, 1);
6257   if (is) {
6258     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6259     PetscCall(ISGetLocalSize(is, &numRows));
6260     PetscCall(ISGetIndices(is, &rows));
6261   }
6262   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6263   if (is) PetscCall(ISRestoreIndices(is, &rows));
6264   PetscFunctionReturn(0);
6265 }
6266 
6267 /*@
6268    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6269    of a set of rows of a matrix. These rows must be local to the process.
6270 
6271    Collective
6272 
6273    Input Parameters:
6274 +  mat - the matrix
6275 .  numRows - the number of rows to remove
6276 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6277 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6278 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6279 -  b - optional vector of right hand side, that will be adjusted by provided solution
6280 
6281    Level: intermediate
6282 
6283    Notes:
6284    See `MatZeroRows()` for details on how this routine operates.
6285 
6286    The grid coordinates are across the entire grid, not just the local portion
6287 
6288    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6289    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6290    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6291    `DM_BOUNDARY_PERIODIC` boundary type.
6292 
6293    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
6294    a single value per point) you can skip filling those indices.
6295 
6296    Fortran Note:
6297    idxm and idxn should be declared as
6298 $     MatStencil idxm(4,m)
6299    and the values inserted using
6300 .vb
6301     idxm(MatStencil_i,1) = i
6302     idxm(MatStencil_j,1) = j
6303     idxm(MatStencil_k,1) = k
6304     idxm(MatStencil_c,1) = c
6305    etc
6306 .ve
6307 
6308 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6309           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6310 @*/
6311 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6312 {
6313   PetscInt  dim    = mat->stencil.dim;
6314   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6315   PetscInt *dims   = mat->stencil.dims + 1;
6316   PetscInt *starts = mat->stencil.starts;
6317   PetscInt *dxm    = (PetscInt *)rows;
6318   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6319 
6320   PetscFunctionBegin;
6321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6322   PetscValidType(mat, 1);
6323   if (numRows) PetscValidPointer(rows, 3);
6324 
6325   PetscCall(PetscMalloc1(numRows, &jdxm));
6326   for (i = 0; i < numRows; ++i) {
6327     /* Skip unused dimensions (they are ordered k, j, i, c) */
6328     for (j = 0; j < 3 - sdim; ++j) dxm++;
6329     /* Local index in X dir */
6330     tmp = *dxm++ - starts[0];
6331     /* Loop over remaining dimensions */
6332     for (j = 0; j < dim - 1; ++j) {
6333       /* If nonlocal, set index to be negative */
6334       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6335       /* Update local index */
6336       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6337     }
6338     /* Skip component slot if necessary */
6339     if (mat->stencil.noc) dxm++;
6340     /* Local row number */
6341     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6342   }
6343   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6344   PetscCall(PetscFree(jdxm));
6345   PetscFunctionReturn(0);
6346 }
6347 
6348 /*@
6349    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6350    of a set of rows and columns of a matrix.
6351 
6352    Collective
6353 
6354    Input Parameters:
6355 +  mat - the matrix
6356 .  numRows - the number of rows/columns to remove
6357 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6358 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6359 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6360 -  b - optional vector of right hand side, that will be adjusted by provided solution
6361 
6362    Level: intermediate
6363 
6364    Notes:
6365    See `MatZeroRowsColumns()` for details on how this routine operates.
6366 
6367    The grid coordinates are across the entire grid, not just the local portion
6368 
6369    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6370    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6371    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6372    `DM_BOUNDARY_PERIODIC` boundary type.
6373 
6374    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
6375    a single value per point) you can skip filling those indices.
6376 
6377    Fortran Note:
6378    In Fortran idxm and idxn should be declared as
6379 $     MatStencil idxm(4,m)
6380    and the values inserted using
6381 .vb
6382     idxm(MatStencil_i,1) = i
6383     idxm(MatStencil_j,1) = j
6384     idxm(MatStencil_k,1) = k
6385     idxm(MatStencil_c,1) = c
6386     etc
6387 .ve
6388 
6389 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6390           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6391 @*/
6392 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6393 {
6394   PetscInt  dim    = mat->stencil.dim;
6395   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6396   PetscInt *dims   = mat->stencil.dims + 1;
6397   PetscInt *starts = mat->stencil.starts;
6398   PetscInt *dxm    = (PetscInt *)rows;
6399   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6400 
6401   PetscFunctionBegin;
6402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6403   PetscValidType(mat, 1);
6404   if (numRows) PetscValidPointer(rows, 3);
6405 
6406   PetscCall(PetscMalloc1(numRows, &jdxm));
6407   for (i = 0; i < numRows; ++i) {
6408     /* Skip unused dimensions (they are ordered k, j, i, c) */
6409     for (j = 0; j < 3 - sdim; ++j) dxm++;
6410     /* Local index in X dir */
6411     tmp = *dxm++ - starts[0];
6412     /* Loop over remaining dimensions */
6413     for (j = 0; j < dim - 1; ++j) {
6414       /* If nonlocal, set index to be negative */
6415       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6416       /* Update local index */
6417       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6418     }
6419     /* Skip component slot if necessary */
6420     if (mat->stencil.noc) dxm++;
6421     /* Local row number */
6422     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6423   }
6424   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6425   PetscCall(PetscFree(jdxm));
6426   PetscFunctionReturn(0);
6427 }
6428 
6429 /*@C
6430    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6431    of a set of rows of a matrix; using local numbering of rows.
6432 
6433    Collective
6434 
6435    Input Parameters:
6436 +  mat - the matrix
6437 .  numRows - the number of rows to remove
6438 .  rows - the local row indices
6439 .  diag - value put in all diagonals of eliminated rows
6440 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6441 -  b - optional vector of right hand side, that will be adjusted by provided solution
6442 
6443    Level: intermediate
6444 
6445    Notes:
6446    Before calling `MatZeroRowsLocal()`, the user must first set the
6447    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6448 
6449    See `MatZeroRows()` for details on how this routine operates.
6450 
6451 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6452           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6453 @*/
6454 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6455 {
6456   PetscFunctionBegin;
6457   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6458   PetscValidType(mat, 1);
6459   if (numRows) PetscValidIntPointer(rows, 3);
6460   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6461   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6462   MatCheckPreallocated(mat, 1);
6463 
6464   if (mat->ops->zerorowslocal) {
6465     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6466   } else {
6467     IS              is, newis;
6468     const PetscInt *newRows;
6469 
6470     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6471     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6472     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6473     PetscCall(ISGetIndices(newis, &newRows));
6474     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6475     PetscCall(ISRestoreIndices(newis, &newRows));
6476     PetscCall(ISDestroy(&newis));
6477     PetscCall(ISDestroy(&is));
6478   }
6479   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6480   PetscFunctionReturn(0);
6481 }
6482 
6483 /*@
6484    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6485    of a set of rows of a matrix; using local numbering of rows.
6486 
6487    Collective
6488 
6489    Input Parameters:
6490 +  mat - the matrix
6491 .  is - index set of rows to remove
6492 .  diag - value put in all diagonals of eliminated rows
6493 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6494 -  b - optional vector of right hand side, that will be adjusted by provided solution
6495 
6496    Level: intermediate
6497 
6498    Notes:
6499    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6500    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6501 
6502    See `MatZeroRows()` for details on how this routine operates.
6503 
6504 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6505           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6506 @*/
6507 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6508 {
6509   PetscInt        numRows;
6510   const PetscInt *rows;
6511 
6512   PetscFunctionBegin;
6513   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6514   PetscValidType(mat, 1);
6515   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6516   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6517   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6518   MatCheckPreallocated(mat, 1);
6519 
6520   PetscCall(ISGetLocalSize(is, &numRows));
6521   PetscCall(ISGetIndices(is, &rows));
6522   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6523   PetscCall(ISRestoreIndices(is, &rows));
6524   PetscFunctionReturn(0);
6525 }
6526 
6527 /*@
6528    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6529    of a set of rows and columns of a matrix; using local numbering of rows.
6530 
6531    Collective
6532 
6533    Input Parameters:
6534 +  mat - the matrix
6535 .  numRows - the number of rows to remove
6536 .  rows - the global row indices
6537 .  diag - value put in all diagonals of eliminated rows
6538 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6539 -  b - optional vector of right hand side, that will be adjusted by provided solution
6540 
6541    Level: intermediate
6542 
6543    Notes:
6544    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6545    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6546 
6547    See `MatZeroRowsColumns()` for details on how this routine operates.
6548 
6549 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6550           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6551 @*/
6552 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6553 {
6554   IS              is, newis;
6555   const PetscInt *newRows;
6556 
6557   PetscFunctionBegin;
6558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6559   PetscValidType(mat, 1);
6560   if (numRows) PetscValidIntPointer(rows, 3);
6561   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6562   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6563   MatCheckPreallocated(mat, 1);
6564 
6565   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6566   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6567   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6568   PetscCall(ISGetIndices(newis, &newRows));
6569   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6570   PetscCall(ISRestoreIndices(newis, &newRows));
6571   PetscCall(ISDestroy(&newis));
6572   PetscCall(ISDestroy(&is));
6573   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6574   PetscFunctionReturn(0);
6575 }
6576 
6577 /*@
6578    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6579    of a set of rows and columns of a matrix; using local numbering of rows.
6580 
6581    Collective on Mat
6582 
6583    Input Parameters:
6584 +  mat - the matrix
6585 .  is - index set of rows to remove
6586 .  diag - value put in all diagonals of eliminated rows
6587 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6588 -  b - optional vector of right hand side, that will be adjusted by provided solution
6589 
6590    Level: intermediate
6591 
6592    Notes:
6593    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6594    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6595 
6596    See `MatZeroRowsColumns()` for details on how this routine operates.
6597 
6598 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6599           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6600 @*/
6601 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6602 {
6603   PetscInt        numRows;
6604   const PetscInt *rows;
6605 
6606   PetscFunctionBegin;
6607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6608   PetscValidType(mat, 1);
6609   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6610   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6611   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6612   MatCheckPreallocated(mat, 1);
6613 
6614   PetscCall(ISGetLocalSize(is, &numRows));
6615   PetscCall(ISGetIndices(is, &rows));
6616   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6617   PetscCall(ISRestoreIndices(is, &rows));
6618   PetscFunctionReturn(0);
6619 }
6620 
6621 /*@C
6622    MatGetSize - Returns the numbers of rows and columns in a matrix.
6623 
6624    Not Collective
6625 
6626    Input Parameter:
6627 .  mat - the matrix
6628 
6629    Level: beginner
6630 
6631    Output Parameters:
6632 +  m - the number of global rows
6633 -  n - the number of global columns
6634 
6635    Note:
6636    Both output parameters can be `NULL` on input.
6637 
6638 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6639 @*/
6640 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6641 {
6642   PetscFunctionBegin;
6643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6644   if (m) *m = mat->rmap->N;
6645   if (n) *n = mat->cmap->N;
6646   PetscFunctionReturn(0);
6647 }
6648 
6649 /*@C
6650    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6651    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6652 
6653    Not Collective
6654 
6655    Input Parameter:
6656 .  mat - the matrix
6657 
6658    Output Parameters:
6659 +  m - the number of local rows, use `NULL` to not obtain this value
6660 -  n - the number of local columns, use `NULL` to not obtain this value
6661 
6662    Level: beginner
6663 
6664 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6665 @*/
6666 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6667 {
6668   PetscFunctionBegin;
6669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6670   if (m) PetscValidIntPointer(m, 2);
6671   if (n) PetscValidIntPointer(n, 3);
6672   if (m) *m = mat->rmap->n;
6673   if (n) *n = mat->cmap->n;
6674   PetscFunctionReturn(0);
6675 }
6676 
6677 /*@C
6678    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6679    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6680 
6681    Not Collective, unless matrix has not been allocated, then collective
6682 
6683    Input Parameter:
6684 .  mat - the matrix
6685 
6686    Output Parameters:
6687 +  m - the global index of the first local column, use `NULL` to not obtain this value
6688 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6689 
6690    Level: developer
6691 
6692 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6693 @*/
6694 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6695 {
6696   PetscFunctionBegin;
6697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6698   PetscValidType(mat, 1);
6699   if (m) PetscValidIntPointer(m, 2);
6700   if (n) PetscValidIntPointer(n, 3);
6701   MatCheckPreallocated(mat, 1);
6702   if (m) *m = mat->cmap->rstart;
6703   if (n) *n = mat->cmap->rend;
6704   PetscFunctionReturn(0);
6705 }
6706 
6707 /*@C
6708    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6709    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
6710    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6711 
6712    Not Collective
6713 
6714    Input Parameter:
6715 .  mat - the matrix
6716 
6717    Output Parameters:
6718 +  m - the global index of the first local row, use `NULL` to not obtain this value
6719 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6720 
6721    Level: beginner
6722 
6723    Note:
6724   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6725   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6726   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6727 
6728 .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6729           `PetscLayout`
6730 @*/
6731 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6732 {
6733   PetscFunctionBegin;
6734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6735   PetscValidType(mat, 1);
6736   if (m) PetscValidIntPointer(m, 2);
6737   if (n) PetscValidIntPointer(n, 3);
6738   MatCheckPreallocated(mat, 1);
6739   if (m) *m = mat->rmap->rstart;
6740   if (n) *n = mat->rmap->rend;
6741   PetscFunctionReturn(0);
6742 }
6743 
6744 /*@C
6745    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6746    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
6747    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6748 
6749    Not Collective, unless matrix has not been allocated, then collective
6750 
6751    Input Parameters:
6752 .  mat - the matrix
6753 
6754    Output Parameters:
6755 .  ranges - start of each processors portion plus one more than the total length at the end
6756 
6757    Level: beginner
6758 
6759 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6760 @*/
6761 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6762 {
6763   PetscFunctionBegin;
6764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6765   PetscValidType(mat, 1);
6766   MatCheckPreallocated(mat, 1);
6767   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6768   PetscFunctionReturn(0);
6769 }
6770 
6771 /*@C
6772    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6773    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6774 
6775    Not Collective, unless matrix has not been allocated, then collective on Mat
6776 
6777    Input Parameters:
6778 .  mat - the matrix
6779 
6780    Output Parameters:
6781 .  ranges - start of each processors portion plus one more then the total length at the end
6782 
6783    Level: beginner
6784 
6785 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6786 @*/
6787 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6788 {
6789   PetscFunctionBegin;
6790   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6791   PetscValidType(mat, 1);
6792   MatCheckPreallocated(mat, 1);
6793   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6794   PetscFunctionReturn(0);
6795 }
6796 
6797 /*@C
6798    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6799    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6800    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6801 
6802    Not Collective
6803 
6804    Input Parameter:
6805 .  A - matrix
6806 
6807    Output Parameters:
6808 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6809 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6810 
6811    Level: intermediate
6812 
6813 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6814 @*/
6815 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6816 {
6817   PetscErrorCode (*f)(Mat, IS *, IS *);
6818 
6819   PetscFunctionBegin;
6820   MatCheckPreallocated(A, 1);
6821   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6822   if (f) {
6823     PetscCall((*f)(A, rows, cols));
6824   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6825     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6826     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6827   }
6828   PetscFunctionReturn(0);
6829 }
6830 
6831 /*@C
6832    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6833    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6834    to complete the factorization.
6835 
6836    Collective on fact
6837 
6838    Input Parameters:
6839 +  fact - the factorized matrix obtained with `MatGetFactor()`
6840 .  mat - the matrix
6841 .  row - row permutation
6842 .  column - column permutation
6843 -  info - structure containing
6844 .vb
6845       levels - number of levels of fill.
6846       expected fill - as ratio of original fill.
6847       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6848                 missing diagonal entries)
6849 .ve
6850 
6851    Output Parameters:
6852 .  fact - new matrix that has been symbolically factored
6853 
6854    Level: developer
6855 
6856    Notes:
6857    See [Matrix Factorization](sec_matfactor) for additional information.
6858 
6859    Most users should employ the `KSP` interface for linear solvers
6860    instead of working directly with matrix algebra routines such as this.
6861    See, e.g., `KSPCreate()`.
6862 
6863    Uses the definition of level of fill as in Y. Saad, 2003
6864 
6865    Developer Note:
6866    The Fortran interface is not autogenerated as the
6867    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6868 
6869    References:
6870 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6871 
6872 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6873           `MatGetOrdering()`, `MatFactorInfo`
6874 @*/
6875 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6876 {
6877   PetscFunctionBegin;
6878   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6879   PetscValidType(mat, 2);
6880   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6881   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6882   PetscValidPointer(info, 5);
6883   PetscValidPointer(fact, 1);
6884   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6885   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6886   if (!fact->ops->ilufactorsymbolic) {
6887     MatSolverType stype;
6888     PetscCall(MatFactorGetSolverType(fact, &stype));
6889     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6890   }
6891   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6892   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6893   MatCheckPreallocated(mat, 2);
6894 
6895   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6896   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6897   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6898   PetscFunctionReturn(0);
6899 }
6900 
6901 /*@C
6902    MatICCFactorSymbolic - Performs symbolic incomplete
6903    Cholesky factorization for a symmetric matrix.  Use
6904    `MatCholeskyFactorNumeric()` to complete the factorization.
6905 
6906    Collective on fact
6907 
6908    Input Parameters:
6909 +  fact - the factorized matrix obtained with `MatGetFactor()`
6910 .  mat - the matrix to be factored
6911 .  perm - row and column permutation
6912 -  info - structure containing
6913 .vb
6914       levels - number of levels of fill.
6915       expected fill - as ratio of original fill.
6916 .ve
6917 
6918    Output Parameter:
6919 .  fact - the factored matrix
6920 
6921    Level: developer
6922 
6923    Notes:
6924    Most users should employ the `KSP` interface for linear solvers
6925    instead of working directly with matrix algebra routines such as this.
6926    See, e.g., `KSPCreate()`.
6927 
6928    This uses the definition of level of fill as in Y. Saad, 2003
6929 
6930    Developer Note:
6931    The Fortran interface is not autogenerated as the
6932    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6933 
6934    References:
6935 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6936 
6937 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6938 @*/
6939 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6940 {
6941   PetscFunctionBegin;
6942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6943   PetscValidType(mat, 2);
6944   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6945   PetscValidPointer(info, 4);
6946   PetscValidPointer(fact, 1);
6947   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6948   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6949   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6950   if (!(fact)->ops->iccfactorsymbolic) {
6951     MatSolverType stype;
6952     PetscCall(MatFactorGetSolverType(fact, &stype));
6953     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6954   }
6955   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6956   MatCheckPreallocated(mat, 2);
6957 
6958   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6959   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6960   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6961   PetscFunctionReturn(0);
6962 }
6963 
6964 /*@C
6965    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6966    points to an array of valid matrices, they may be reused to store the new
6967    submatrices.
6968 
6969    Collective
6970 
6971    Input Parameters:
6972 +  mat - the matrix
6973 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6974 .  irow, icol - index sets of rows and columns to extract
6975 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6976 
6977    Output Parameter:
6978 .  submat - the array of submatrices
6979 
6980    Level: advanced
6981 
6982    Notes:
6983    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6984    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6985    to extract a parallel submatrix.
6986 
6987    Some matrix types place restrictions on the row and column
6988    indices, such as that they be sorted or that they be equal to each other.
6989 
6990    The index sets may not have duplicate entries.
6991 
6992    When extracting submatrices from a parallel matrix, each processor can
6993    form a different submatrix by setting the rows and columns of its
6994    individual index sets according to the local submatrix desired.
6995 
6996    When finished using the submatrices, the user should destroy
6997    them with `MatDestroySubMatrices()`.
6998 
6999    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7000    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7001 
7002    This routine creates the matrices in submat; you should NOT create them before
7003    calling it. It also allocates the array of matrix pointers submat.
7004 
7005    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7006    request one row/column in a block, they must request all rows/columns that are in
7007    that block. For example, if the block size is 2 you cannot request just row 0 and
7008    column 0.
7009 
7010    Fortran Note:
7011    The Fortran interface is slightly different from that given below; it
7012    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
7013 
7014 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7015 @*/
7016 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7017 {
7018   PetscInt  i;
7019   PetscBool eq;
7020 
7021   PetscFunctionBegin;
7022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7023   PetscValidType(mat, 1);
7024   if (n) {
7025     PetscValidPointer(irow, 3);
7026     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7027     PetscValidPointer(icol, 4);
7028     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7029   }
7030   PetscValidPointer(submat, 6);
7031   if (n && scall == MAT_REUSE_MATRIX) {
7032     PetscValidPointer(*submat, 6);
7033     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7034   }
7035   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7036   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7037   MatCheckPreallocated(mat, 1);
7038   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7039   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7040   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7041   for (i = 0; i < n; i++) {
7042     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7043     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7044     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7045 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7046     if (mat->boundtocpu && mat->bindingpropagates) {
7047       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7048       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7049     }
7050 #endif
7051   }
7052   PetscFunctionReturn(0);
7053 }
7054 
7055 /*@C
7056    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7057 
7058    Collective
7059 
7060    Input Parameters:
7061 +  mat - the matrix
7062 .  n   - the number of submatrixes to be extracted
7063 .  irow, icol - index sets of rows and columns to extract
7064 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7065 
7066    Output Parameter:
7067 .  submat - the array of submatrices
7068 
7069    Level: advanced
7070 
7071    Note:
7072    This is used by `PCGASM`
7073 
7074 .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7075 @*/
7076 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7077 {
7078   PetscInt  i;
7079   PetscBool eq;
7080 
7081   PetscFunctionBegin;
7082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7083   PetscValidType(mat, 1);
7084   if (n) {
7085     PetscValidPointer(irow, 3);
7086     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7087     PetscValidPointer(icol, 4);
7088     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7089   }
7090   PetscValidPointer(submat, 6);
7091   if (n && scall == MAT_REUSE_MATRIX) {
7092     PetscValidPointer(*submat, 6);
7093     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7094   }
7095   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7096   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7097   MatCheckPreallocated(mat, 1);
7098 
7099   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7100   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7101   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7102   for (i = 0; i < n; i++) {
7103     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7104     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7105   }
7106   PetscFunctionReturn(0);
7107 }
7108 
7109 /*@C
7110    MatDestroyMatrices - Destroys an array of matrices.
7111 
7112    Collective
7113 
7114    Input Parameters:
7115 +  n - the number of local matrices
7116 -  mat - the matrices (note that this is a pointer to the array of matrices)
7117 
7118    Level: advanced
7119 
7120     Note:
7121     Frees not only the matrices, but also the array that contains the matrices
7122 
7123     Fortran Note:
7124     Will not free the array.
7125 
7126 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7127 @*/
7128 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7129 {
7130   PetscInt i;
7131 
7132   PetscFunctionBegin;
7133   if (!*mat) PetscFunctionReturn(0);
7134   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7135   PetscValidPointer(mat, 2);
7136 
7137   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7138 
7139   /* memory is allocated even if n = 0 */
7140   PetscCall(PetscFree(*mat));
7141   PetscFunctionReturn(0);
7142 }
7143 
7144 /*@C
7145    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7146 
7147    Collective
7148 
7149    Input Parameters:
7150 +  n - the number of local matrices
7151 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7152                        sequence of MatCreateSubMatrices())
7153 
7154    Level: advanced
7155 
7156     Note:
7157     Frees not only the matrices, but also the array that contains the matrices
7158 
7159     Fortran Note:
7160     Will not free the array.
7161 
7162 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7163 @*/
7164 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7165 {
7166   Mat mat0;
7167 
7168   PetscFunctionBegin;
7169   if (!*mat) PetscFunctionReturn(0);
7170   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7171   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7172   PetscValidPointer(mat, 2);
7173 
7174   mat0 = (*mat)[0];
7175   if (mat0 && mat0->ops->destroysubmatrices) {
7176     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7177   } else {
7178     PetscCall(MatDestroyMatrices(n, mat));
7179   }
7180   PetscFunctionReturn(0);
7181 }
7182 
7183 /*@C
7184    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7185 
7186    Collective
7187 
7188    Input Parameters:
7189 .  mat - the matrix
7190 
7191    Output Parameter:
7192 .  matstruct - the sequential matrix with the nonzero structure of mat
7193 
7194   Level: developer
7195 
7196 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7197 @*/
7198 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7199 {
7200   PetscFunctionBegin;
7201   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7202   PetscValidPointer(matstruct, 2);
7203 
7204   PetscValidType(mat, 1);
7205   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7206   MatCheckPreallocated(mat, 1);
7207 
7208   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7209   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7210   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7211   PetscFunctionReturn(0);
7212 }
7213 
7214 /*@C
7215    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7216 
7217    Collective
7218 
7219    Input Parameters:
7220 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7221                        sequence of `MatGetSequentialNonzeroStructure()`)
7222 
7223    Level: advanced
7224 
7225     Note:
7226     Frees not only the matrices, but also the array that contains the matrices
7227 
7228 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7229 @*/
7230 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7231 {
7232   PetscFunctionBegin;
7233   PetscValidPointer(mat, 1);
7234   PetscCall(MatDestroy(mat));
7235   PetscFunctionReturn(0);
7236 }
7237 
7238 /*@
7239    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7240    replaces the index sets by larger ones that represent submatrices with
7241    additional overlap.
7242 
7243    Collective
7244 
7245    Input Parameters:
7246 +  mat - the matrix
7247 .  n   - the number of index sets
7248 .  is  - the array of index sets (these index sets will changed during the call)
7249 -  ov  - the additional overlap requested
7250 
7251    Options Database Key:
7252 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7253 
7254    Level: developer
7255 
7256    Note:
7257    The computed overlap preserves the matrix block sizes when the blocks are square.
7258    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7259    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7260 
7261 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7262 @*/
7263 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7264 {
7265   PetscInt i, bs, cbs;
7266 
7267   PetscFunctionBegin;
7268   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7269   PetscValidType(mat, 1);
7270   PetscValidLogicalCollectiveInt(mat, n, 2);
7271   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7272   if (n) {
7273     PetscValidPointer(is, 3);
7274     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7275   }
7276   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7277   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7278   MatCheckPreallocated(mat, 1);
7279 
7280   if (!ov || !n) PetscFunctionReturn(0);
7281   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7282   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7283   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7284   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7285   if (bs == cbs) {
7286     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7287   }
7288   PetscFunctionReturn(0);
7289 }
7290 
7291 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7292 
7293 /*@
7294    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7295    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7296    additional overlap.
7297 
7298    Collective
7299 
7300    Input Parameters:
7301 +  mat - the matrix
7302 .  n   - the number of index sets
7303 .  is  - the array of index sets (these index sets will changed during the call)
7304 -  ov  - the additional overlap requested
7305 
7306 `   Options Database Key:
7307 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7308 
7309    Level: developer
7310 
7311 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7312 @*/
7313 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7314 {
7315   PetscInt i;
7316 
7317   PetscFunctionBegin;
7318   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7319   PetscValidType(mat, 1);
7320   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7321   if (n) {
7322     PetscValidPointer(is, 3);
7323     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7324   }
7325   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7326   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7327   MatCheckPreallocated(mat, 1);
7328   if (!ov) PetscFunctionReturn(0);
7329   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7330   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7331   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7332   PetscFunctionReturn(0);
7333 }
7334 
7335 /*@
7336    MatGetBlockSize - Returns the matrix block size.
7337 
7338    Not Collective
7339 
7340    Input Parameter:
7341 .  mat - the matrix
7342 
7343    Output Parameter:
7344 .  bs - block size
7345 
7346    Level: intermediate
7347 
7348    Notes:
7349     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7350 
7351    If the block size has not been set yet this routine returns 1.
7352 
7353 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7354 @*/
7355 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7356 {
7357   PetscFunctionBegin;
7358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7359   PetscValidIntPointer(bs, 2);
7360   *bs = PetscAbs(mat->rmap->bs);
7361   PetscFunctionReturn(0);
7362 }
7363 
7364 /*@
7365    MatGetBlockSizes - Returns the matrix block row and column sizes.
7366 
7367    Not Collective
7368 
7369    Input Parameter:
7370 .  mat - the matrix
7371 
7372    Output Parameters:
7373 +  rbs - row block size
7374 -  cbs - column block size
7375 
7376    Level: intermediate
7377 
7378    Notes:
7379     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7380     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7381 
7382    If a block size has not been set yet this routine returns 1.
7383 
7384 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7385 @*/
7386 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7387 {
7388   PetscFunctionBegin;
7389   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7390   if (rbs) PetscValidIntPointer(rbs, 2);
7391   if (cbs) PetscValidIntPointer(cbs, 3);
7392   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7393   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7394   PetscFunctionReturn(0);
7395 }
7396 
7397 /*@
7398    MatSetBlockSize - Sets the matrix block size.
7399 
7400    Logically Collective
7401 
7402    Input Parameters:
7403 +  mat - the matrix
7404 -  bs - block size
7405 
7406    Level: intermediate
7407 
7408    Notes:
7409     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7410     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7411 
7412     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7413     is compatible with the matrix local sizes.
7414 
7415 .seealso: `Mat`,  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7416 @*/
7417 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7418 {
7419   PetscFunctionBegin;
7420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7421   PetscValidLogicalCollectiveInt(mat, bs, 2);
7422   PetscCall(MatSetBlockSizes(mat, bs, bs));
7423   PetscFunctionReturn(0);
7424 }
7425 
7426 typedef struct {
7427   PetscInt         n;
7428   IS              *is;
7429   Mat             *mat;
7430   PetscObjectState nonzerostate;
7431   Mat              C;
7432 } EnvelopeData;
7433 
7434 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7435 {
7436   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7437   PetscCall(PetscFree(edata->is));
7438   PetscCall(PetscFree(edata));
7439   return 0;
7440 }
7441 
7442 /*
7443    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7444          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7445 
7446    Collective
7447 
7448    Input Parameter:
7449 .  mat - the matrix
7450 
7451    Notes:
7452      There can be zeros within the blocks
7453 
7454      The blocks can overlap between processes, including laying on more than two processes
7455 
7456 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7457 */
7458 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7459 {
7460   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7461   PetscInt          *diag, *odiag, sc;
7462   VecScatter         scatter;
7463   PetscScalar       *seqv;
7464   const PetscScalar *parv;
7465   const PetscInt    *ia, *ja;
7466   PetscBool          set, flag, done;
7467   Mat                AA = mat, A;
7468   MPI_Comm           comm;
7469   PetscMPIInt        rank, size, tag;
7470   MPI_Status         status;
7471   PetscContainer     container;
7472   EnvelopeData      *edata;
7473   Vec                seq, par;
7474   IS                 isglobal;
7475 
7476   PetscFunctionBegin;
7477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7478   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7479   if (!set || !flag) {
7480     /* TOO: only needs nonzero structure of transpose */
7481     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7482     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7483   }
7484   PetscCall(MatAIJGetLocalMat(AA, &A));
7485   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7486   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7487 
7488   PetscCall(MatGetLocalSize(mat, &n, NULL));
7489   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7490   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7491   PetscCallMPI(MPI_Comm_size(comm, &size));
7492   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7493 
7494   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7495 
7496   if (rank > 0) {
7497     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7498     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7499   }
7500   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7501   for (i = 0; i < n; i++) {
7502     env = PetscMax(env, ja[ia[i + 1] - 1]);
7503     II  = rstart + i;
7504     if (env == II) {
7505       starts[lblocks]  = tbs;
7506       sizes[lblocks++] = 1 + II - tbs;
7507       tbs              = 1 + II;
7508     }
7509   }
7510   if (rank < size - 1) {
7511     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7512     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7513   }
7514 
7515   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7516   if (!set || !flag) PetscCall(MatDestroy(&AA));
7517   PetscCall(MatDestroy(&A));
7518 
7519   PetscCall(PetscNew(&edata));
7520   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7521   edata->n = lblocks;
7522   /* create IS needed for extracting blocks from the original matrix */
7523   PetscCall(PetscMalloc1(lblocks, &edata->is));
7524   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7525 
7526   /* Create the resulting inverse matrix structure with preallocation information */
7527   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7528   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7529   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7530   PetscCall(MatSetType(edata->C, MATAIJ));
7531 
7532   /* Communicate the start and end of each row, from each block to the correct rank */
7533   /* TODO: Use PetscSF instead of VecScatter */
7534   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7535   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7536   PetscCall(VecGetArrayWrite(seq, &seqv));
7537   for (PetscInt i = 0; i < lblocks; i++) {
7538     for (PetscInt j = 0; j < sizes[i]; j++) {
7539       seqv[cnt]     = starts[i];
7540       seqv[cnt + 1] = starts[i] + sizes[i];
7541       cnt += 2;
7542     }
7543   }
7544   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7545   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7546   sc -= cnt;
7547   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7548   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7549   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7550   PetscCall(ISDestroy(&isglobal));
7551   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7552   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7553   PetscCall(VecScatterDestroy(&scatter));
7554   PetscCall(VecDestroy(&seq));
7555   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7556   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7557   PetscCall(VecGetArrayRead(par, &parv));
7558   cnt = 0;
7559   PetscCall(MatGetSize(mat, NULL, &n));
7560   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7561     PetscInt start, end, d = 0, od = 0;
7562 
7563     start = (PetscInt)PetscRealPart(parv[cnt]);
7564     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7565     cnt += 2;
7566 
7567     if (start < cstart) {
7568       od += cstart - start + n - cend;
7569       d += cend - cstart;
7570     } else if (start < cend) {
7571       od += n - cend;
7572       d += cend - start;
7573     } else od += n - start;
7574     if (end <= cstart) {
7575       od -= cstart - end + n - cend;
7576       d -= cend - cstart;
7577     } else if (end < cend) {
7578       od -= n - cend;
7579       d -= cend - end;
7580     } else od -= n - end;
7581 
7582     odiag[i] = od;
7583     diag[i]  = d;
7584   }
7585   PetscCall(VecRestoreArrayRead(par, &parv));
7586   PetscCall(VecDestroy(&par));
7587   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7588   PetscCall(PetscFree2(diag, odiag));
7589   PetscCall(PetscFree2(sizes, starts));
7590 
7591   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7592   PetscCall(PetscContainerSetPointer(container, edata));
7593   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7594   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7595   PetscCall(PetscObjectDereference((PetscObject)container));
7596   PetscFunctionReturn(0);
7597 }
7598 
7599 /*@
7600   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7601 
7602   Collective
7603 
7604   Input Parameters:
7605 . A - the matrix
7606 
7607   Output Parameters:
7608 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7609 
7610   Level: advanced
7611 
7612   Note:
7613      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7614 
7615 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7616 @*/
7617 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7618 {
7619   PetscContainer   container;
7620   EnvelopeData    *edata;
7621   PetscObjectState nonzerostate;
7622 
7623   PetscFunctionBegin;
7624   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7625   if (!container) {
7626     PetscCall(MatComputeVariableBlockEnvelope(A));
7627     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7628   }
7629   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7630   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7631   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7632   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7633 
7634   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7635   *C = edata->C;
7636 
7637   for (PetscInt i = 0; i < edata->n; i++) {
7638     Mat          D;
7639     PetscScalar *dvalues;
7640 
7641     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7642     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7643     PetscCall(MatSeqDenseInvert(D));
7644     PetscCall(MatDenseGetArray(D, &dvalues));
7645     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7646     PetscCall(MatDestroy(&D));
7647   }
7648   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7649   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7650   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7651   PetscFunctionReturn(0);
7652 }
7653 
7654 /*@
7655    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7656 
7657    Logically Collective
7658 
7659    Input Parameters:
7660 +  mat - the matrix
7661 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7662 -  bsizes - the block sizes
7663 
7664    Level: intermediate
7665 
7666    Notes:
7667     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7668 
7669     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.
7670 
7671 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7672           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7673 @*/
7674 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7675 {
7676   PetscInt i, ncnt = 0, nlocal;
7677 
7678   PetscFunctionBegin;
7679   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7680   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7681   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7682   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7683   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);
7684   PetscCall(PetscFree(mat->bsizes));
7685   mat->nblocks = nblocks;
7686   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7687   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7688   PetscFunctionReturn(0);
7689 }
7690 
7691 /*@C
7692    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7693 
7694    Logically Collective; No Fortran Support
7695 
7696    Input Parameter:
7697 .  mat - the matrix
7698 
7699    Output Parameters:
7700 +  nblocks - the number of blocks on this process
7701 -  bsizes - the block sizes
7702 
7703    Level: intermediate
7704 
7705 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7706 @*/
7707 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7708 {
7709   PetscFunctionBegin;
7710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7711   *nblocks = mat->nblocks;
7712   *bsizes  = mat->bsizes;
7713   PetscFunctionReturn(0);
7714 }
7715 
7716 /*@
7717    MatSetBlockSizes - Sets the matrix block row and column sizes.
7718 
7719    Logically Collective
7720 
7721    Input Parameters:
7722 +  mat - the matrix
7723 .  rbs - row block size
7724 -  cbs - column block size
7725 
7726    Level: intermediate
7727 
7728    Notes:
7729     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7730     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7731     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7732 
7733     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7734     are compatible with the matrix local sizes.
7735 
7736     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7737 
7738 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7739 @*/
7740 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7741 {
7742   PetscFunctionBegin;
7743   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7744   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7745   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7746   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7747   if (mat->rmap->refcnt) {
7748     ISLocalToGlobalMapping l2g  = NULL;
7749     PetscLayout            nmap = NULL;
7750 
7751     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7752     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7753     PetscCall(PetscLayoutDestroy(&mat->rmap));
7754     mat->rmap          = nmap;
7755     mat->rmap->mapping = l2g;
7756   }
7757   if (mat->cmap->refcnt) {
7758     ISLocalToGlobalMapping l2g  = NULL;
7759     PetscLayout            nmap = NULL;
7760 
7761     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7762     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7763     PetscCall(PetscLayoutDestroy(&mat->cmap));
7764     mat->cmap          = nmap;
7765     mat->cmap->mapping = l2g;
7766   }
7767   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7768   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7769   PetscFunctionReturn(0);
7770 }
7771 
7772 /*@
7773    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7774 
7775    Logically Collective
7776 
7777    Input Parameters:
7778 +  mat - the matrix
7779 .  fromRow - matrix from which to copy row block size
7780 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7781 
7782    Level: developer
7783 
7784 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7785 @*/
7786 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7787 {
7788   PetscFunctionBegin;
7789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7790   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7791   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7792   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7793   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7794   PetscFunctionReturn(0);
7795 }
7796 
7797 /*@
7798    MatResidual - Default routine to calculate the residual r = b - Ax
7799 
7800    Collective
7801 
7802    Input Parameters:
7803 +  mat - the matrix
7804 .  b   - the right-hand-side
7805 -  x   - the approximate solution
7806 
7807    Output Parameter:
7808 .  r - location to store the residual
7809 
7810    Level: developer
7811 
7812 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7813 @*/
7814 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7815 {
7816   PetscFunctionBegin;
7817   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7818   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7819   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7820   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7821   PetscValidType(mat, 1);
7822   MatCheckPreallocated(mat, 1);
7823   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7824   if (!mat->ops->residual) {
7825     PetscCall(MatMult(mat, x, r));
7826     PetscCall(VecAYPX(r, -1.0, b));
7827   } else {
7828     PetscUseTypeMethod(mat, residual, b, x, r);
7829   }
7830   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7831   PetscFunctionReturn(0);
7832 }
7833 
7834 /*@C
7835     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7836 
7837    Collective
7838 
7839     Input Parameters:
7840 +   mat - the matrix
7841 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7842 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7843 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7844                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7845                  always used.
7846 
7847     Output Parameters:
7848 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7849 .   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
7850 .   ja - the column indices, use `NULL` if not needed
7851 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7852            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7853 
7854     Level: developer
7855 
7856     Notes:
7857     You CANNOT change any of the ia[] or ja[] values.
7858 
7859     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7860 
7861     Fortran Notes:
7862     In Fortran use
7863 .vb
7864       PetscInt ia(1), ja(1)
7865       PetscOffset iia, jja
7866       call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7867       ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7868 .ve
7869      or
7870 .vb
7871     PetscInt, pointer :: ia(:),ja(:)
7872     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7873     ! Access the ith and jth entries via ia(i) and ja(j)
7874 .ve
7875 
7876 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7877 @*/
7878 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7879 {
7880   PetscFunctionBegin;
7881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7882   PetscValidType(mat, 1);
7883   if (n) PetscValidIntPointer(n, 5);
7884   if (ia) PetscValidPointer(ia, 6);
7885   if (ja) PetscValidPointer(ja, 7);
7886   if (done) PetscValidBoolPointer(done, 8);
7887   MatCheckPreallocated(mat, 1);
7888   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7889   else {
7890     if (done) *done = PETSC_TRUE;
7891     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7892     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7893     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7894   }
7895   PetscFunctionReturn(0);
7896 }
7897 
7898 /*@C
7899     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7900 
7901     Collective
7902 
7903     Input Parameters:
7904 +   mat - the matrix
7905 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7906 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7907                 symmetrized
7908 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7909                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7910                  always used.
7911 .   n - number of columns in the (possibly compressed) matrix
7912 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7913 -   ja - the row indices
7914 
7915     Output Parameters:
7916 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7917 
7918     Level: developer
7919 
7920 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7921 @*/
7922 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7923 {
7924   PetscFunctionBegin;
7925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7926   PetscValidType(mat, 1);
7927   PetscValidIntPointer(n, 5);
7928   if (ia) PetscValidPointer(ia, 6);
7929   if (ja) PetscValidPointer(ja, 7);
7930   PetscValidBoolPointer(done, 8);
7931   MatCheckPreallocated(mat, 1);
7932   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7933   else {
7934     *done = PETSC_TRUE;
7935     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7936   }
7937   PetscFunctionReturn(0);
7938 }
7939 
7940 /*@C
7941     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7942 
7943     Collective
7944 
7945     Input Parameters:
7946 +   mat - the matrix
7947 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7948 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7949 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7950                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7951                  always used.
7952 .   n - size of (possibly compressed) matrix
7953 .   ia - the row pointers
7954 -   ja - the column indices
7955 
7956     Output Parameters:
7957 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7958 
7959     Level: developer
7960 
7961     Note:
7962     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7963     us of the array after it has been restored. If you pass `NULL`, it will
7964     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7965 
7966 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7967 @*/
7968 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7969 {
7970   PetscFunctionBegin;
7971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7972   PetscValidType(mat, 1);
7973   if (ia) PetscValidPointer(ia, 6);
7974   if (ja) PetscValidPointer(ja, 7);
7975   if (done) PetscValidBoolPointer(done, 8);
7976   MatCheckPreallocated(mat, 1);
7977 
7978   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7979   else {
7980     if (done) *done = PETSC_TRUE;
7981     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7982     if (n) *n = 0;
7983     if (ia) *ia = NULL;
7984     if (ja) *ja = NULL;
7985   }
7986   PetscFunctionReturn(0);
7987 }
7988 
7989 /*@C
7990     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7991 
7992     Collective on Mat
7993 
7994     Input Parameters:
7995 +   mat - the matrix
7996 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7997 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7998 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7999                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8000                  always used.
8001 
8002     Output Parameters:
8003 +   n - size of (possibly compressed) matrix
8004 .   ia - the column pointers
8005 .   ja - the row indices
8006 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8007 
8008     Level: developer
8009 
8010 .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8011 @*/
8012 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8013 {
8014   PetscFunctionBegin;
8015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8016   PetscValidType(mat, 1);
8017   if (ia) PetscValidPointer(ia, 6);
8018   if (ja) PetscValidPointer(ja, 7);
8019   PetscValidBoolPointer(done, 8);
8020   MatCheckPreallocated(mat, 1);
8021 
8022   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8023   else {
8024     *done = PETSC_TRUE;
8025     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8026     if (n) *n = 0;
8027     if (ia) *ia = NULL;
8028     if (ja) *ja = NULL;
8029   }
8030   PetscFunctionReturn(0);
8031 }
8032 
8033 /*@C
8034     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8035 
8036     Collective
8037 
8038     Input Parameters:
8039 +   mat - the matrix
8040 .   ncolors - max color value
8041 .   n   - number of entries in colorarray
8042 -   colorarray - array indicating color for each column
8043 
8044     Output Parameters:
8045 .   iscoloring - coloring generated using colorarray information
8046 
8047     Level: developer
8048 
8049 .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8050 @*/
8051 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8052 {
8053   PetscFunctionBegin;
8054   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8055   PetscValidType(mat, 1);
8056   PetscValidIntPointer(colorarray, 4);
8057   PetscValidPointer(iscoloring, 5);
8058   MatCheckPreallocated(mat, 1);
8059 
8060   if (!mat->ops->coloringpatch) {
8061     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8062   } else {
8063     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8064   }
8065   PetscFunctionReturn(0);
8066 }
8067 
8068 /*@
8069    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8070 
8071    Logically Collective
8072 
8073    Input Parameter:
8074 .  mat - the factored matrix to be reset
8075 
8076    Level: developer
8077 
8078    Notes:
8079    This routine should be used only with factored matrices formed by in-place
8080    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8081    format).  This option can save memory, for example, when solving nonlinear
8082    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8083    ILU(0) preconditioner.
8084 
8085    Note that one can specify in-place ILU(0) factorization by calling
8086 .vb
8087      PCType(pc,PCILU);
8088      PCFactorSeUseInPlace(pc);
8089 .ve
8090    or by using the options -pc_type ilu -pc_factor_in_place
8091 
8092    In-place factorization ILU(0) can also be used as a local
8093    solver for the blocks within the block Jacobi or additive Schwarz
8094    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8095    for details on setting local solver options.
8096 
8097    Most users should employ the `KSP` interface for linear solvers
8098    instead of working directly with matrix algebra routines such as this.
8099    See, e.g., `KSPCreate()`.
8100 
8101 .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8102 @*/
8103 PetscErrorCode MatSetUnfactored(Mat mat)
8104 {
8105   PetscFunctionBegin;
8106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8107   PetscValidType(mat, 1);
8108   MatCheckPreallocated(mat, 1);
8109   mat->factortype = MAT_FACTOR_NONE;
8110   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
8111   PetscUseTypeMethod(mat, setunfactored);
8112   PetscFunctionReturn(0);
8113 }
8114 
8115 /*MC
8116     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8117 
8118     Synopsis:
8119     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8120 
8121     Not collective
8122 
8123     Input Parameter:
8124 .   x - matrix
8125 
8126     Output Parameters:
8127 +   xx_v - the Fortran pointer to the array
8128 -   ierr - error code
8129 
8130     Example of Usage:
8131 .vb
8132       PetscScalar, pointer xx_v(:,:)
8133       ....
8134       call MatDenseGetArrayF90(x,xx_v,ierr)
8135       a = xx_v(3)
8136       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8137 .ve
8138 
8139     Level: advanced
8140 
8141 .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8142 M*/
8143 
8144 /*MC
8145     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8146     accessed with `MatDenseGetArrayF90()`.
8147 
8148     Synopsis:
8149     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8150 
8151     Not collective
8152 
8153     Input Parameters:
8154 +   x - matrix
8155 -   xx_v - the Fortran90 pointer to the array
8156 
8157     Output Parameter:
8158 .   ierr - error code
8159 
8160     Example of Usage:
8161 .vb
8162        PetscScalar, pointer xx_v(:,:)
8163        ....
8164        call MatDenseGetArrayF90(x,xx_v,ierr)
8165        a = xx_v(3)
8166        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8167 .ve
8168 
8169     Level: advanced
8170 
8171 .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8172 M*/
8173 
8174 /*MC
8175     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8176 
8177     Synopsis:
8178     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8179 
8180     Not collective
8181 
8182     Input Parameter:
8183 .   x - matrix
8184 
8185     Output Parameters:
8186 +   xx_v - the Fortran pointer to the array
8187 -   ierr - error code
8188 
8189     Example of Usage:
8190 .vb
8191       PetscScalar, pointer xx_v(:)
8192       ....
8193       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8194       a = xx_v(3)
8195       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8196 .ve
8197 
8198     Level: advanced
8199 
8200 .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8201 M*/
8202 
8203 /*MC
8204     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8205     accessed with `MatSeqAIJGetArrayF90()`.
8206 
8207     Synopsis:
8208     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8209 
8210     Not collective
8211 
8212     Input Parameters:
8213 +   x - matrix
8214 -   xx_v - the Fortran90 pointer to the array
8215 
8216     Output Parameter:
8217 .   ierr - error code
8218 
8219     Example of Usage:
8220 .vb
8221        PetscScalar, pointer xx_v(:)
8222        ....
8223        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8224        a = xx_v(3)
8225        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8226 .ve
8227 
8228     Level: advanced
8229 
8230 .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8231 M*/
8232 
8233 /*@
8234     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8235                       as the original matrix.
8236 
8237     Collective
8238 
8239     Input Parameters:
8240 +   mat - the original matrix
8241 .   isrow - parallel IS containing the rows this processor should obtain
8242 .   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.
8243 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8244 
8245     Output Parameter:
8246 .   newmat - the new submatrix, of the same type as the old
8247 
8248     Level: advanced
8249 
8250     Notes:
8251     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8252 
8253     Some matrix types place restrictions on the row and column indices, such
8254     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;
8255     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8256 
8257     The index sets may not have duplicate entries.
8258 
8259       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8260    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8261    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8262    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8263    you are finished using it.
8264 
8265     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8266     the input matrix.
8267 
8268     If iscol is `NULL` then all columns are obtained (not supported in Fortran).
8269 
8270    Example usage:
8271    Consider the following 8x8 matrix with 34 non-zero values, that is
8272    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8273    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8274    as follows:
8275 
8276 .vb
8277             1  2  0  |  0  3  0  |  0  4
8278     Proc0   0  5  6  |  7  0  0  |  8  0
8279             9  0 10  | 11  0  0  | 12  0
8280     -------------------------------------
8281            13  0 14  | 15 16 17  |  0  0
8282     Proc1   0 18  0  | 19 20 21  |  0  0
8283             0  0  0  | 22 23  0  | 24  0
8284     -------------------------------------
8285     Proc2  25 26 27  |  0  0 28  | 29  0
8286            30  0  0  | 31 32 33  |  0 34
8287 .ve
8288 
8289     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8290 
8291 .vb
8292             2  0  |  0  3  0  |  0
8293     Proc0   5  6  |  7  0  0  |  8
8294     -------------------------------
8295     Proc1  18  0  | 19 20 21  |  0
8296     -------------------------------
8297     Proc2  26 27  |  0  0 28  | 29
8298             0  0  | 31 32 33  |  0
8299 .ve
8300 
8301 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8302 @*/
8303 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8304 {
8305   PetscMPIInt size;
8306   Mat        *local;
8307   IS          iscoltmp;
8308   PetscBool   flg;
8309 
8310   PetscFunctionBegin;
8311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8312   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8313   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8314   PetscValidPointer(newmat, 5);
8315   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8316   PetscValidType(mat, 1);
8317   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8318   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8319 
8320   MatCheckPreallocated(mat, 1);
8321   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8322 
8323   if (!iscol || isrow == iscol) {
8324     PetscBool   stride;
8325     PetscMPIInt grabentirematrix = 0, grab;
8326     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8327     if (stride) {
8328       PetscInt first, step, n, rstart, rend;
8329       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8330       if (step == 1) {
8331         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8332         if (rstart == first) {
8333           PetscCall(ISGetLocalSize(isrow, &n));
8334           if (n == rend - rstart) grabentirematrix = 1;
8335         }
8336       }
8337     }
8338     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8339     if (grab) {
8340       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8341       if (cll == MAT_INITIAL_MATRIX) {
8342         *newmat = mat;
8343         PetscCall(PetscObjectReference((PetscObject)mat));
8344       }
8345       PetscFunctionReturn(0);
8346     }
8347   }
8348 
8349   if (!iscol) {
8350     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8351   } else {
8352     iscoltmp = iscol;
8353   }
8354 
8355   /* if original matrix is on just one processor then use submatrix generated */
8356   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8357     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8358     goto setproperties;
8359   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8360     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8361     *newmat = *local;
8362     PetscCall(PetscFree(local));
8363     goto setproperties;
8364   } else if (!mat->ops->createsubmatrix) {
8365     /* Create a new matrix type that implements the operation using the full matrix */
8366     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8367     switch (cll) {
8368     case MAT_INITIAL_MATRIX:
8369       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8370       break;
8371     case MAT_REUSE_MATRIX:
8372       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8373       break;
8374     default:
8375       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8376     }
8377     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8378     goto setproperties;
8379   }
8380 
8381   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8382   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8383   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8384 
8385 setproperties:
8386   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8387   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8388   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8389   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8390   PetscFunctionReturn(0);
8391 }
8392 
8393 /*@
8394    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8395 
8396    Not Collective
8397 
8398    Input Parameters:
8399 +  A - the matrix we wish to propagate options from
8400 -  B - the matrix we wish to propagate options to
8401 
8402    Level: beginner
8403 
8404    Note:
8405    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8406 
8407 .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8408 @*/
8409 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8410 {
8411   PetscFunctionBegin;
8412   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8413   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8414   B->symmetry_eternal            = A->symmetry_eternal;
8415   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8416   B->symmetric                   = A->symmetric;
8417   B->structurally_symmetric      = A->structurally_symmetric;
8418   B->spd                         = A->spd;
8419   B->hermitian                   = A->hermitian;
8420   PetscFunctionReturn(0);
8421 }
8422 
8423 /*@
8424    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8425    used during the assembly process to store values that belong to
8426    other processors.
8427 
8428    Not Collective
8429 
8430    Input Parameters:
8431 +  mat   - the matrix
8432 .  size  - the initial size of the stash.
8433 -  bsize - the initial size of the block-stash(if used).
8434 
8435    Options Database Keys:
8436 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8437 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8438 
8439    Level: intermediate
8440 
8441    Notes:
8442      The block-stash is used for values set with `MatSetValuesBlocked()` while
8443      the stash is used for values set with `MatSetValues()`
8444 
8445      Run with the option -info and look for output of the form
8446      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8447      to determine the appropriate value, MM, to use for size and
8448      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8449      to determine the value, BMM to use for bsize
8450 
8451 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8452 @*/
8453 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8454 {
8455   PetscFunctionBegin;
8456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8457   PetscValidType(mat, 1);
8458   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8459   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8460   PetscFunctionReturn(0);
8461 }
8462 
8463 /*@
8464    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8465      the matrix
8466 
8467    Neighbor-wise Collective
8468 
8469    Input Parameters:
8470 +  mat   - the matrix
8471 .  x,y - the vectors
8472 -  w - where the result is stored
8473 
8474    Level: intermediate
8475 
8476    Notes:
8477     `w` may be the same vector as `y`.
8478 
8479     This allows one to use either the restriction or interpolation (its transpose)
8480     matrix to do the interpolation
8481 
8482 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8483 @*/
8484 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8485 {
8486   PetscInt M, N, Ny;
8487 
8488   PetscFunctionBegin;
8489   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8490   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8491   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8492   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8493   PetscCall(MatGetSize(A, &M, &N));
8494   PetscCall(VecGetSize(y, &Ny));
8495   if (M == Ny) {
8496     PetscCall(MatMultAdd(A, x, y, w));
8497   } else {
8498     PetscCall(MatMultTransposeAdd(A, x, y, w));
8499   }
8500   PetscFunctionReturn(0);
8501 }
8502 
8503 /*@
8504    MatInterpolate - y = A*x or A'*x depending on the shape of
8505      the matrix
8506 
8507    Neighbor-wise Collective
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 interpolation
8518 
8519 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8520 @*/
8521 PetscErrorCode MatInterpolate(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    MatRestrict - y = A*x or A'*x
8541 
8542    Neighbor-wise Collective on Mat
8543 
8544    Input Parameters:
8545 +  mat   - the matrix
8546 -  x,y - the vectors
8547 
8548    Level: intermediate
8549 
8550    Note:
8551     This allows one to use either the restriction or interpolation (its transpose)
8552     matrix to do the restriction
8553 
8554 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8555 @*/
8556 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8557 {
8558   PetscInt M, N, Ny;
8559 
8560   PetscFunctionBegin;
8561   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8562   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8563   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8564   PetscCall(MatGetSize(A, &M, &N));
8565   PetscCall(VecGetSize(y, &Ny));
8566   if (M == Ny) {
8567     PetscCall(MatMult(A, x, y));
8568   } else {
8569     PetscCall(MatMultTranspose(A, x, y));
8570   }
8571   PetscFunctionReturn(0);
8572 }
8573 
8574 /*@
8575    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8576 
8577    Neighbor-wise Collective on Mat
8578 
8579    Input Parameters:
8580 +  mat   - the matrix
8581 -  w, x - the input dense matrices
8582 
8583    Output Parameters:
8584 .  y - the output dense matrix
8585 
8586    Level: intermediate
8587 
8588    Note:
8589     This allows one to use either the restriction or interpolation (its transpose)
8590     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8591     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8592 
8593 .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8594 @*/
8595 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8596 {
8597   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8598   PetscBool trans = PETSC_TRUE;
8599   MatReuse  reuse = MAT_INITIAL_MATRIX;
8600 
8601   PetscFunctionBegin;
8602   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8603   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8604   PetscValidType(x, 2);
8605   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8606   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8607   PetscCall(MatGetSize(A, &M, &N));
8608   PetscCall(MatGetSize(x, &Mx, &Nx));
8609   if (N == Mx) trans = PETSC_FALSE;
8610   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);
8611   Mo = trans ? N : M;
8612   if (*y) {
8613     PetscCall(MatGetSize(*y, &My, &Ny));
8614     if (Mo == My && Nx == Ny) {
8615       reuse = MAT_REUSE_MATRIX;
8616     } else {
8617       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);
8618       PetscCall(MatDestroy(y));
8619     }
8620   }
8621 
8622   if (w && *y == w) { /* this is to minimize changes in PCMG */
8623     PetscBool flg;
8624 
8625     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8626     if (w) {
8627       PetscInt My, Ny, Mw, Nw;
8628 
8629       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8630       PetscCall(MatGetSize(*y, &My, &Ny));
8631       PetscCall(MatGetSize(w, &Mw, &Nw));
8632       if (!flg || My != Mw || Ny != Nw) w = NULL;
8633     }
8634     if (!w) {
8635       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8636       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8637       PetscCall(PetscObjectDereference((PetscObject)w));
8638     } else {
8639       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8640     }
8641   }
8642   if (!trans) {
8643     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8644   } else {
8645     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8646   }
8647   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8648   PetscFunctionReturn(0);
8649 }
8650 
8651 /*@
8652    MatMatInterpolate - Y = A*X or A'*X
8653 
8654    Neighbor-wise Collective on Mat
8655 
8656    Input Parameters:
8657 +  mat   - the matrix
8658 -  x - the input dense matrix
8659 
8660    Output Parameters:
8661 .  y - the output dense matrix
8662 
8663    Level: intermediate
8664 
8665    Note:
8666     This allows one to use either the restriction or interpolation (its transpose)
8667     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8668     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8669 
8670 .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8671 @*/
8672 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8673 {
8674   PetscFunctionBegin;
8675   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8676   PetscFunctionReturn(0);
8677 }
8678 
8679 /*@
8680    MatMatRestrict - Y = A*X or A'*X
8681 
8682    Neighbor-wise Collective on Mat
8683 
8684    Input Parameters:
8685 +  mat   - the matrix
8686 -  x - the input dense matrix
8687 
8688    Output Parameters:
8689 .  y - the output dense matrix
8690 
8691    Level: intermediate
8692 
8693    Note:
8694     This allows one to use either the restriction or interpolation (its transpose)
8695     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8696     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8697 
8698 .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8699 @*/
8700 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8701 {
8702   PetscFunctionBegin;
8703   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8704   PetscFunctionReturn(0);
8705 }
8706 
8707 /*@
8708    MatGetNullSpace - retrieves the null space of a matrix.
8709 
8710    Logically Collective
8711 
8712    Input Parameters:
8713 +  mat - the matrix
8714 -  nullsp - the null space object
8715 
8716    Level: developer
8717 
8718 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8719 @*/
8720 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8721 {
8722   PetscFunctionBegin;
8723   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8724   PetscValidPointer(nullsp, 2);
8725   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8726   PetscFunctionReturn(0);
8727 }
8728 
8729 /*@
8730    MatSetNullSpace - attaches a null space to a matrix.
8731 
8732    Logically Collective
8733 
8734    Input Parameters:
8735 +  mat - the matrix
8736 -  nullsp - the null space object
8737 
8738    Level: advanced
8739 
8740    Notes:
8741       This null space is used by the `KSP` linear solvers to solve singular systems.
8742 
8743       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`
8744 
8745       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
8746       to zero but the linear system will still be solved in a least squares sense.
8747 
8748       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8749    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).
8750    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
8751    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
8752    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).
8753    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8754 
8755     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8756     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8757     routine also automatically calls `MatSetTransposeNullSpace()`.
8758 
8759     The user should call `MatNullSpaceDestroy()`.
8760 
8761 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8762           `KSPSetPCSide()`
8763 @*/
8764 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8765 {
8766   PetscFunctionBegin;
8767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8768   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8769   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8770   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8771   mat->nullsp = nullsp;
8772   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8773   PetscFunctionReturn(0);
8774 }
8775 
8776 /*@
8777    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8778 
8779    Logically Collective
8780 
8781    Input Parameters:
8782 +  mat - the matrix
8783 -  nullsp - the null space object
8784 
8785    Level: developer
8786 
8787 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8788 @*/
8789 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8790 {
8791   PetscFunctionBegin;
8792   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8793   PetscValidType(mat, 1);
8794   PetscValidPointer(nullsp, 2);
8795   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8796   PetscFunctionReturn(0);
8797 }
8798 
8799 /*@
8800    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8801 
8802    Logically Collective
8803 
8804    Input Parameters:
8805 +  mat - the matrix
8806 -  nullsp - the null space object
8807 
8808    Level: advanced
8809 
8810    Notes:
8811    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8812 
8813    See `MatSetNullSpace()`
8814 
8815 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8816 @*/
8817 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8818 {
8819   PetscFunctionBegin;
8820   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8821   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8822   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8823   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8824   mat->transnullsp = nullsp;
8825   PetscFunctionReturn(0);
8826 }
8827 
8828 /*@
8829    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8830         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8831 
8832    Logically Collective
8833 
8834    Input Parameters:
8835 +  mat - the matrix
8836 -  nullsp - the null space object
8837 
8838    Level: advanced
8839 
8840    Notes:
8841    Overwrites any previous near null space that may have been attached
8842 
8843    You can remove the null space by calling this routine with an nullsp of `NULL`
8844 
8845 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8846 @*/
8847 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8848 {
8849   PetscFunctionBegin;
8850   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8851   PetscValidType(mat, 1);
8852   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8853   MatCheckPreallocated(mat, 1);
8854   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8855   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8856   mat->nearnullsp = nullsp;
8857   PetscFunctionReturn(0);
8858 }
8859 
8860 /*@
8861    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8862 
8863    Not Collective
8864 
8865    Input Parameter:
8866 .  mat - the matrix
8867 
8868    Output Parameter:
8869 .  nullsp - the null space object, `NULL` if not set
8870 
8871    Level: advanced
8872 
8873 .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8874 @*/
8875 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8876 {
8877   PetscFunctionBegin;
8878   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8879   PetscValidType(mat, 1);
8880   PetscValidPointer(nullsp, 2);
8881   MatCheckPreallocated(mat, 1);
8882   *nullsp = mat->nearnullsp;
8883   PetscFunctionReturn(0);
8884 }
8885 
8886 /*@C
8887    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8888 
8889    Collective
8890 
8891    Input Parameters:
8892 +  mat - the matrix
8893 .  row - row/column permutation
8894 .  fill - expected fill factor >= 1.0
8895 -  level - level of fill, for ICC(k)
8896 
8897    Notes:
8898    Probably really in-place only when level of fill is zero, otherwise allocates
8899    new space to store factored matrix and deletes previous memory.
8900 
8901    Most users should employ the `KSP` interface for linear solvers
8902    instead of working directly with matrix algebra routines such as this.
8903    See, e.g., `KSPCreate()`.
8904 
8905    Level: developer
8906 
8907    Developer Note:
8908    The Fortran interface is not autogenerated as the
8909    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8910 
8911 .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8912 @*/
8913 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8914 {
8915   PetscFunctionBegin;
8916   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8917   PetscValidType(mat, 1);
8918   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8919   PetscValidPointer(info, 3);
8920   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8921   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8922   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8923   MatCheckPreallocated(mat, 1);
8924   PetscUseTypeMethod(mat, iccfactor, row, info);
8925   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8926   PetscFunctionReturn(0);
8927 }
8928 
8929 /*@
8930    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8931          ghosted ones.
8932 
8933    Not Collective
8934 
8935    Input Parameters:
8936 +  mat - the matrix
8937 -  diag - the diagonal values, including ghost ones
8938 
8939    Level: developer
8940 
8941    Notes:
8942     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8943 
8944     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8945 
8946 .seealso: `Mat`, `MatDiagonalScale()`
8947 @*/
8948 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8949 {
8950   PetscMPIInt size;
8951 
8952   PetscFunctionBegin;
8953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8954   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8955   PetscValidType(mat, 1);
8956 
8957   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8958   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8959   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8960   if (size == 1) {
8961     PetscInt n, m;
8962     PetscCall(VecGetSize(diag, &n));
8963     PetscCall(MatGetSize(mat, NULL, &m));
8964     if (m == n) {
8965       PetscCall(MatDiagonalScale(mat, NULL, diag));
8966     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8967   } else {
8968     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8969   }
8970   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8971   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8972   PetscFunctionReturn(0);
8973 }
8974 
8975 /*@
8976    MatGetInertia - Gets the inertia from a factored matrix
8977 
8978    Collective
8979 
8980    Input Parameter:
8981 .  mat - the matrix
8982 
8983    Output Parameters:
8984 +   nneg - number of negative eigenvalues
8985 .   nzero - number of zero eigenvalues
8986 -   npos - number of positive eigenvalues
8987 
8988    Level: advanced
8989 
8990    Note:
8991     Matrix must have been factored by `MatCholeskyFactor()`
8992 
8993 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
8994 @*/
8995 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
8996 {
8997   PetscFunctionBegin;
8998   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8999   PetscValidType(mat, 1);
9000   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9001   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9002   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9003   PetscFunctionReturn(0);
9004 }
9005 
9006 /*@C
9007    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9008 
9009    Neighbor-wise Collective
9010 
9011    Input Parameters:
9012 +  mat - the factored matrix obtained with `MatGetFactor()`
9013 -  b - the right-hand-side vectors
9014 
9015    Output Parameter:
9016 .  x - the result vectors
9017 
9018    Level: developer
9019 
9020    Note:
9021    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9022    call `MatSolves`(A,x,x).
9023 
9024 .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9025 @*/
9026 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9027 {
9028   PetscFunctionBegin;
9029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9030   PetscValidType(mat, 1);
9031   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9032   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9033   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
9034 
9035   MatCheckPreallocated(mat, 1);
9036   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9037   PetscUseTypeMethod(mat, solves, b, x);
9038   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9039   PetscFunctionReturn(0);
9040 }
9041 
9042 /*@
9043    MatIsSymmetric - Test whether a matrix is symmetric
9044 
9045    Collective
9046 
9047    Input Parameters:
9048 +  A - the matrix to test
9049 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9050 
9051    Output Parameters:
9052 .  flg - the result
9053 
9054    Level: intermediate
9055 
9056    Notes:
9057     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9058 
9059     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9060 
9061     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9062     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9063 
9064 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9065           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9066 @*/
9067 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9068 {
9069   PetscFunctionBegin;
9070   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9071   PetscValidBoolPointer(flg, 3);
9072 
9073   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9074   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9075   else {
9076     if (!A->ops->issymmetric) {
9077       MatType mattype;
9078       PetscCall(MatGetType(A, &mattype));
9079       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9080     }
9081     PetscUseTypeMethod(A, issymmetric, tol, flg);
9082     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9083   }
9084   PetscFunctionReturn(0);
9085 }
9086 
9087 /*@
9088    MatIsHermitian - Test whether a matrix is Hermitian
9089 
9090    Collective on Mat
9091 
9092    Input Parameters:
9093 +  A - the matrix to test
9094 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9095 
9096    Output Parameters:
9097 .  flg - the result
9098 
9099    Level: intermediate
9100 
9101    Notes:
9102     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9103 
9104     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9105 
9106     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9107     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9108 
9109 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9110           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9111 @*/
9112 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9113 {
9114   PetscFunctionBegin;
9115   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9116   PetscValidBoolPointer(flg, 3);
9117 
9118   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9119   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9120   else {
9121     if (!A->ops->ishermitian) {
9122       MatType mattype;
9123       PetscCall(MatGetType(A, &mattype));
9124       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9125     }
9126     PetscUseTypeMethod(A, ishermitian, tol, flg);
9127     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9128   }
9129   PetscFunctionReturn(0);
9130 }
9131 
9132 /*@
9133    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9134 
9135    Not Collective
9136 
9137    Input Parameter:
9138 .  A - the matrix to check
9139 
9140    Output Parameters:
9141 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9142 -  flg - the result (only valid if set is `PETSC_TRUE`)
9143 
9144    Level: advanced
9145 
9146    Notes:
9147    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9148    if you want it explicitly checked
9149 
9150     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9151     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9152 
9153 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9154 @*/
9155 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9156 {
9157   PetscFunctionBegin;
9158   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9159   PetscValidBoolPointer(set, 2);
9160   PetscValidBoolPointer(flg, 3);
9161   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9162     *set = PETSC_TRUE;
9163     *flg = PetscBool3ToBool(A->symmetric);
9164   } else {
9165     *set = PETSC_FALSE;
9166   }
9167   PetscFunctionReturn(0);
9168 }
9169 
9170 /*@
9171    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9172 
9173    Not Collective
9174 
9175    Input Parameter:
9176 .  A - the matrix to check
9177 
9178    Output Parameters:
9179 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9180 -  flg - the result (only valid if set is `PETSC_TRUE`)
9181 
9182    Level: advanced
9183 
9184    Notes:
9185    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9186 
9187    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9188    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9189 
9190 .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9191 @*/
9192 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9193 {
9194   PetscFunctionBegin;
9195   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9196   PetscValidBoolPointer(set, 2);
9197   PetscValidBoolPointer(flg, 3);
9198   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9199     *set = PETSC_TRUE;
9200     *flg = PetscBool3ToBool(A->spd);
9201   } else {
9202     *set = PETSC_FALSE;
9203   }
9204   PetscFunctionReturn(0);
9205 }
9206 
9207 /*@
9208    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9209 
9210    Not Collective
9211 
9212    Input Parameter:
9213 .  A - the matrix to check
9214 
9215    Output Parameters:
9216 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9217 -  flg - the result (only valid if set is `PETSC_TRUE`)
9218 
9219    Level: advanced
9220 
9221    Notes:
9222    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9223    if you want it explicitly checked
9224 
9225    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9226    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9227 
9228 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9229 @*/
9230 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9231 {
9232   PetscFunctionBegin;
9233   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9234   PetscValidBoolPointer(set, 2);
9235   PetscValidBoolPointer(flg, 3);
9236   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9237     *set = PETSC_TRUE;
9238     *flg = PetscBool3ToBool(A->hermitian);
9239   } else {
9240     *set = PETSC_FALSE;
9241   }
9242   PetscFunctionReturn(0);
9243 }
9244 
9245 /*@
9246    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9247 
9248    Collective on Mat
9249 
9250    Input Parameter:
9251 .  A - the matrix to test
9252 
9253    Output Parameters:
9254 .  flg - the result
9255 
9256    Level: intermediate
9257 
9258    Notes:
9259    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9260 
9261    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
9262    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9263 
9264 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9265 @*/
9266 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9267 {
9268   PetscFunctionBegin;
9269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9270   PetscValidBoolPointer(flg, 2);
9271   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9272     *flg = PetscBool3ToBool(A->structurally_symmetric);
9273   } else {
9274     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9275     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9276   }
9277   PetscFunctionReturn(0);
9278 }
9279 
9280 /*@
9281    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9282 
9283    Not Collective
9284 
9285    Input Parameter:
9286 .  A - the matrix to check
9287 
9288    Output Parameters:
9289 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9290 -  flg - the result (only valid if set is PETSC_TRUE)
9291 
9292    Level: advanced
9293 
9294    Notes:
9295    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
9296    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9297 
9298    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9299 
9300 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9301 @*/
9302 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9303 {
9304   PetscFunctionBegin;
9305   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9306   PetscValidBoolPointer(set, 2);
9307   PetscValidBoolPointer(flg, 3);
9308   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9309     *set = PETSC_TRUE;
9310     *flg = PetscBool3ToBool(A->structurally_symmetric);
9311   } else {
9312     *set = PETSC_FALSE;
9313   }
9314   PetscFunctionReturn(0);
9315 }
9316 
9317 /*@
9318    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9319        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9320 
9321     Not collective
9322 
9323    Input Parameter:
9324 .   mat - the matrix
9325 
9326    Output Parameters:
9327 +   nstash   - the size of the stash
9328 .   reallocs - the number of additional mallocs incurred.
9329 .   bnstash   - the size of the block stash
9330 -   breallocs - the number of additional mallocs incurred.in the block stash
9331 
9332    Level: advanced
9333 
9334 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9335 @*/
9336 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9337 {
9338   PetscFunctionBegin;
9339   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9340   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9341   PetscFunctionReturn(0);
9342 }
9343 
9344 /*@C
9345    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9346    parallel layout, `PetscLayout` for rows and columns
9347 
9348    Collective
9349 
9350    Input Parameter:
9351 .  mat - the matrix
9352 
9353    Output Parameters:
9354 +   right - (optional) vector that the matrix can be multiplied against
9355 -   left - (optional) vector that the matrix vector product can be stored in
9356 
9357   Level: advanced
9358 
9359    Notes:
9360     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()`.
9361 
9362     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9363 
9364 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9365 @*/
9366 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9367 {
9368   PetscFunctionBegin;
9369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9370   PetscValidType(mat, 1);
9371   if (mat->ops->getvecs) {
9372     PetscUseTypeMethod(mat, getvecs, right, left);
9373   } else {
9374     PetscInt rbs, cbs;
9375     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9376     if (right) {
9377       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9378       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9379       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9380       PetscCall(VecSetBlockSize(*right, cbs));
9381       PetscCall(VecSetType(*right, mat->defaultvectype));
9382 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9383       if (mat->boundtocpu && mat->bindingpropagates) {
9384         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9385         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9386       }
9387 #endif
9388       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9389     }
9390     if (left) {
9391       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9392       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9393       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9394       PetscCall(VecSetBlockSize(*left, rbs));
9395       PetscCall(VecSetType(*left, mat->defaultvectype));
9396 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9397       if (mat->boundtocpu && mat->bindingpropagates) {
9398         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9399         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9400       }
9401 #endif
9402       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9403     }
9404   }
9405   PetscFunctionReturn(0);
9406 }
9407 
9408 /*@C
9409    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9410      with default values.
9411 
9412    Not Collective
9413 
9414    Input Parameters:
9415 .    info - the `MatFactorInfo` data structure
9416 
9417    Level: developer
9418 
9419    Notes:
9420     The solvers are generally used through the `KSP` and `PC` objects, for example
9421           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9422 
9423     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9424 
9425    Developer Note:
9426    The Fortran interface is not autogenerated as the
9427    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9428 
9429 .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo`
9430 @*/
9431 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9432 {
9433   PetscFunctionBegin;
9434   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9435   PetscFunctionReturn(0);
9436 }
9437 
9438 /*@
9439    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9440 
9441    Collective
9442 
9443    Input Parameters:
9444 +  mat - the factored matrix
9445 -  is - the index set defining the Schur indices (0-based)
9446 
9447    Level: advanced
9448 
9449    Notes:
9450     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9451 
9452    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9453 
9454    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9455 
9456 .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9457           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9458 @*/
9459 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9460 {
9461   PetscErrorCode (*f)(Mat, IS);
9462 
9463   PetscFunctionBegin;
9464   PetscValidType(mat, 1);
9465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9466   PetscValidType(is, 2);
9467   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9468   PetscCheckSameComm(mat, 1, is, 2);
9469   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9470   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9471   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9472   PetscCall(MatDestroy(&mat->schur));
9473   PetscCall((*f)(mat, is));
9474   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9475   PetscFunctionReturn(0);
9476 }
9477 
9478 /*@
9479   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9480 
9481    Logically Collective
9482 
9483    Input Parameters:
9484 +  F - the factored matrix obtained by calling `MatGetFactor()`
9485 .  S - location where to return the Schur complement, can be `NULL`
9486 -  status - the status of the Schur complement matrix, can be `NULL`
9487 
9488    Level: advanced
9489 
9490    Notes:
9491    You must call `MatFactorSetSchurIS()` before calling this routine.
9492 
9493    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9494 
9495    The routine provides a copy of the Schur matrix stored within the solver data structures.
9496    The caller must destroy the object when it is no longer needed.
9497    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9498 
9499    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)
9500 
9501    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9502 
9503    Developer Note:
9504     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9505    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9506 
9507 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9508 @*/
9509 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9510 {
9511   PetscFunctionBegin;
9512   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9513   if (S) PetscValidPointer(S, 2);
9514   if (status) PetscValidPointer(status, 3);
9515   if (S) {
9516     PetscErrorCode (*f)(Mat, Mat *);
9517 
9518     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9519     if (f) {
9520       PetscCall((*f)(F, S));
9521     } else {
9522       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9523     }
9524   }
9525   if (status) *status = F->schur_status;
9526   PetscFunctionReturn(0);
9527 }
9528 
9529 /*@
9530   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9531 
9532    Logically Collective
9533 
9534    Input Parameters:
9535 +  F - the factored matrix obtained by calling `MatGetFactor()`
9536 .  *S - location where to return the Schur complement, can be `NULL`
9537 -  status - the status of the Schur complement matrix, can be `NULL`
9538 
9539    Level: advanced
9540 
9541    Notes:
9542    You must call `MatFactorSetSchurIS()` before calling this routine.
9543 
9544    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9545 
9546    The routine returns a the Schur Complement stored within the data structures of the solver.
9547 
9548    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9549 
9550    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9551 
9552    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9553 
9554    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9555 
9556 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9557 @*/
9558 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9559 {
9560   PetscFunctionBegin;
9561   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9562   if (S) PetscValidPointer(S, 2);
9563   if (status) PetscValidPointer(status, 3);
9564   if (S) *S = F->schur;
9565   if (status) *status = F->schur_status;
9566   PetscFunctionReturn(0);
9567 }
9568 
9569 /*@
9570   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9571 
9572    Logically Collective
9573 
9574    Input Parameters:
9575 +  F - the factored matrix obtained by calling `MatGetFactor()`
9576 .  *S - location where the Schur complement is stored
9577 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9578 
9579    Level: advanced
9580 
9581 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9582 @*/
9583 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9584 {
9585   PetscFunctionBegin;
9586   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9587   if (S) {
9588     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9589     *S = NULL;
9590   }
9591   F->schur_status = status;
9592   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9593   PetscFunctionReturn(0);
9594 }
9595 
9596 /*@
9597   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9598 
9599    Logically Collective
9600 
9601    Input Parameters:
9602 +  F - the factored matrix obtained by calling `MatGetFactor()`
9603 .  rhs - location where the right hand side of the Schur complement system is stored
9604 -  sol - location where the solution of the Schur complement system has to be returned
9605 
9606    Level: advanced
9607 
9608    Notes:
9609    The sizes of the vectors should match the size of the Schur complement
9610 
9611    Must be called after `MatFactorSetSchurIS()`
9612 
9613 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9614 @*/
9615 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9616 {
9617   PetscFunctionBegin;
9618   PetscValidType(F, 1);
9619   PetscValidType(rhs, 2);
9620   PetscValidType(sol, 3);
9621   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9622   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9623   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9624   PetscCheckSameComm(F, 1, rhs, 2);
9625   PetscCheckSameComm(F, 1, sol, 3);
9626   PetscCall(MatFactorFactorizeSchurComplement(F));
9627   switch (F->schur_status) {
9628   case MAT_FACTOR_SCHUR_FACTORED:
9629     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9630     break;
9631   case MAT_FACTOR_SCHUR_INVERTED:
9632     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9633     break;
9634   default:
9635     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9636   }
9637   PetscFunctionReturn(0);
9638 }
9639 
9640 /*@
9641   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9642 
9643    Logically Collective
9644 
9645    Input Parameters:
9646 +  F - the factored matrix obtained by calling `MatGetFactor()`
9647 .  rhs - location where the right hand side of the Schur complement system is stored
9648 -  sol - location where the solution of the Schur complement system has to be returned
9649 
9650    Level: advanced
9651 
9652    Notes:
9653    The sizes of the vectors should match the size of the Schur complement
9654 
9655    Must be called after `MatFactorSetSchurIS()`
9656 
9657 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9658 @*/
9659 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9660 {
9661   PetscFunctionBegin;
9662   PetscValidType(F, 1);
9663   PetscValidType(rhs, 2);
9664   PetscValidType(sol, 3);
9665   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9666   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9667   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9668   PetscCheckSameComm(F, 1, rhs, 2);
9669   PetscCheckSameComm(F, 1, sol, 3);
9670   PetscCall(MatFactorFactorizeSchurComplement(F));
9671   switch (F->schur_status) {
9672   case MAT_FACTOR_SCHUR_FACTORED:
9673     PetscCall(MatSolve(F->schur, rhs, sol));
9674     break;
9675   case MAT_FACTOR_SCHUR_INVERTED:
9676     PetscCall(MatMult(F->schur, rhs, sol));
9677     break;
9678   default:
9679     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9680   }
9681   PetscFunctionReturn(0);
9682 }
9683 
9684 /*@
9685   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9686 
9687    Logically Collective on F
9688 
9689    Input Parameters:
9690 .  F - the factored matrix obtained by calling `MatGetFactor()`
9691 
9692    Level: advanced
9693 
9694    Notes:
9695     Must be called after `MatFactorSetSchurIS()`.
9696 
9697    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9698 
9699 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9700 @*/
9701 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9702 {
9703   PetscFunctionBegin;
9704   PetscValidType(F, 1);
9705   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9706   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9707   PetscCall(MatFactorFactorizeSchurComplement(F));
9708   PetscCall(MatFactorInvertSchurComplement_Private(F));
9709   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9710   PetscFunctionReturn(0);
9711 }
9712 
9713 /*@
9714   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9715 
9716    Logically Collective
9717 
9718    Input Parameters:
9719 .  F - the factored matrix obtained by calling `MatGetFactor()`
9720 
9721    Level: advanced
9722 
9723    Note:
9724     Must be called after `MatFactorSetSchurIS()`
9725 
9726 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9727 @*/
9728 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9729 {
9730   PetscFunctionBegin;
9731   PetscValidType(F, 1);
9732   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9733   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9734   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9735   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9736   PetscFunctionReturn(0);
9737 }
9738 
9739 /*@
9740    MatPtAP - Creates the matrix product C = P^T * A * P
9741 
9742    Neighbor-wise Collective
9743 
9744    Input Parameters:
9745 +  A - the matrix
9746 .  P - the projection matrix
9747 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9748 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9749           if the result is a dense matrix this is irrelevant
9750 
9751    Output Parameters:
9752 .  C - the product matrix
9753 
9754    Level: intermediate
9755 
9756    Notes:
9757    C will be created and must be destroyed by the user with `MatDestroy()`.
9758 
9759    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9760 
9761    Developer Note:
9762    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9763 
9764 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9765 @*/
9766 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9767 {
9768   PetscFunctionBegin;
9769   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9770   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9771 
9772   if (scall == MAT_INITIAL_MATRIX) {
9773     PetscCall(MatProductCreate(A, P, NULL, C));
9774     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9775     PetscCall(MatProductSetAlgorithm(*C, "default"));
9776     PetscCall(MatProductSetFill(*C, fill));
9777 
9778     (*C)->product->api_user = PETSC_TRUE;
9779     PetscCall(MatProductSetFromOptions(*C));
9780     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);
9781     PetscCall(MatProductSymbolic(*C));
9782   } else { /* scall == MAT_REUSE_MATRIX */
9783     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9784   }
9785 
9786   PetscCall(MatProductNumeric(*C));
9787   (*C)->symmetric = A->symmetric;
9788   (*C)->spd       = A->spd;
9789   PetscFunctionReturn(0);
9790 }
9791 
9792 /*@
9793    MatRARt - Creates the matrix product C = R * A * R^T
9794 
9795    Neighbor-wise Collective
9796 
9797    Input Parameters:
9798 +  A - the matrix
9799 .  R - the projection matrix
9800 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9801 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9802           if the result is a dense matrix this is irrelevant
9803 
9804    Output Parameters:
9805 .  C - the product matrix
9806 
9807    Level: intermediate
9808 
9809    Notes:
9810    C will be created and must be destroyed by the user with `MatDestroy()`.
9811 
9812    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9813 
9814    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9815    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9816    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9817    We recommend using MatPtAP().
9818 
9819 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9820 @*/
9821 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9822 {
9823   PetscFunctionBegin;
9824   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9825   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9826 
9827   if (scall == MAT_INITIAL_MATRIX) {
9828     PetscCall(MatProductCreate(A, R, NULL, C));
9829     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9830     PetscCall(MatProductSetAlgorithm(*C, "default"));
9831     PetscCall(MatProductSetFill(*C, fill));
9832 
9833     (*C)->product->api_user = PETSC_TRUE;
9834     PetscCall(MatProductSetFromOptions(*C));
9835     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);
9836     PetscCall(MatProductSymbolic(*C));
9837   } else { /* scall == MAT_REUSE_MATRIX */
9838     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9839   }
9840 
9841   PetscCall(MatProductNumeric(*C));
9842   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9843   PetscFunctionReturn(0);
9844 }
9845 
9846 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9847 {
9848   PetscFunctionBegin;
9849   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9850 
9851   if (scall == MAT_INITIAL_MATRIX) {
9852     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9853     PetscCall(MatProductCreate(A, B, NULL, C));
9854     PetscCall(MatProductSetType(*C, ptype));
9855     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9856     PetscCall(MatProductSetFill(*C, fill));
9857 
9858     (*C)->product->api_user = PETSC_TRUE;
9859     PetscCall(MatProductSetFromOptions(*C));
9860     PetscCall(MatProductSymbolic(*C));
9861   } else { /* scall == MAT_REUSE_MATRIX */
9862     Mat_Product *product = (*C)->product;
9863     PetscBool    isdense;
9864 
9865     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9866     if (isdense && product && product->type != ptype) {
9867       PetscCall(MatProductClear(*C));
9868       product = NULL;
9869     }
9870     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9871     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9872       if (isdense) {
9873         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9874         product           = (*C)->product;
9875         product->fill     = fill;
9876         product->api_user = PETSC_TRUE;
9877         product->clear    = PETSC_TRUE;
9878 
9879         PetscCall(MatProductSetType(*C, ptype));
9880         PetscCall(MatProductSetFromOptions(*C));
9881         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);
9882         PetscCall(MatProductSymbolic(*C));
9883       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9884     } else { /* user may change input matrices A or B when REUSE */
9885       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9886     }
9887   }
9888   PetscCall(MatProductNumeric(*C));
9889   PetscFunctionReturn(0);
9890 }
9891 
9892 /*@
9893    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9894 
9895    Neighbor-wise Collective
9896 
9897    Input Parameters:
9898 +  A - the left matrix
9899 .  B - the right matrix
9900 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9901 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9902           if the result is a dense matrix this is irrelevant
9903 
9904    Output Parameters:
9905 .  C - the product matrix
9906 
9907    Notes:
9908    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9909 
9910    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
9911    call to this function with `MAT_INITIAL_MATRIX`.
9912 
9913    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9914 
9915    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`,
9916    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9917 
9918    Example of Usage:
9919 .vb
9920      MatProductCreate(A,B,NULL,&C);
9921      MatProductSetType(C,MATPRODUCT_AB);
9922      MatProductSymbolic(C);
9923      MatProductNumeric(C); // compute C=A * B
9924      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9925      MatProductNumeric(C);
9926      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9927      MatProductNumeric(C);
9928 .ve
9929 
9930    Level: intermediate
9931 
9932 .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9933 @*/
9934 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9935 {
9936   PetscFunctionBegin;
9937   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9938   PetscFunctionReturn(0);
9939 }
9940 
9941 /*@
9942    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9943 
9944    Neighbor-wise Collective
9945 
9946    Input Parameters:
9947 +  A - the left matrix
9948 .  B - the right matrix
9949 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9950 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9951 
9952    Output Parameters:
9953 .  C - the product matrix
9954 
9955    Level: intermediate
9956 
9957    Notes:
9958    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9959 
9960    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9961 
9962    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9963    actually needed.
9964 
9965    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9966    and for pairs of `MATMPIDENSE` matrices.
9967 
9968    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9969 
9970    Options Database Keys:
9971 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9972               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9973               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9974 
9975 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9976 @*/
9977 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9978 {
9979   PetscFunctionBegin;
9980   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9981   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9982   PetscFunctionReturn(0);
9983 }
9984 
9985 /*@
9986    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9987 
9988    Neighbor-wise Collective
9989 
9990    Input Parameters:
9991 +  A - the left matrix
9992 .  B - the right matrix
9993 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9994 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9995 
9996    Output Parameters:
9997 .  C - the product matrix
9998 
9999    Level: intermediate
10000 
10001    Notes:
10002    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10003 
10004    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10005 
10006    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10007 
10008    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10009    actually needed.
10010 
10011    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10012    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10013 
10014 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10015 @*/
10016 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10017 {
10018   PetscFunctionBegin;
10019   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10020   PetscFunctionReturn(0);
10021 }
10022 
10023 /*@
10024    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10025 
10026    Neighbor-wise Collective
10027 
10028    Input Parameters:
10029 +  A - the left matrix
10030 .  B - the middle matrix
10031 .  C - the right matrix
10032 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10033 -  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
10034           if the result is a dense matrix this is irrelevant
10035 
10036    Output Parameters:
10037 .  D - the product matrix
10038 
10039    Level: intermediate
10040 
10041    Notes:
10042    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10043 
10044    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10045 
10046    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10047 
10048    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10049    actually needed.
10050 
10051    If you have many matrices with the same non-zero structure to multiply, you
10052    should use `MAT_REUSE_MATRIX` in all calls but the first
10053 
10054 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10055 @*/
10056 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10057 {
10058   PetscFunctionBegin;
10059   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10060   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10061 
10062   if (scall == MAT_INITIAL_MATRIX) {
10063     PetscCall(MatProductCreate(A, B, C, D));
10064     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10065     PetscCall(MatProductSetAlgorithm(*D, "default"));
10066     PetscCall(MatProductSetFill(*D, fill));
10067 
10068     (*D)->product->api_user = PETSC_TRUE;
10069     PetscCall(MatProductSetFromOptions(*D));
10070     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,
10071                ((PetscObject)C)->type_name);
10072     PetscCall(MatProductSymbolic(*D));
10073   } else { /* user may change input matrices when REUSE */
10074     PetscCall(MatProductReplaceMats(A, B, C, *D));
10075   }
10076   PetscCall(MatProductNumeric(*D));
10077   PetscFunctionReturn(0);
10078 }
10079 
10080 /*@
10081    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10082 
10083    Collective
10084 
10085    Input Parameters:
10086 +  mat - the matrix
10087 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10088 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10089 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10090 
10091    Output Parameter:
10092 .  matredundant - redundant matrix
10093 
10094    Level: advanced
10095 
10096    Notes:
10097    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10098    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10099 
10100    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10101    calling it.
10102 
10103    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10104 
10105 .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10106 @*/
10107 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10108 {
10109   MPI_Comm       comm;
10110   PetscMPIInt    size;
10111   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10112   Mat_Redundant *redund     = NULL;
10113   PetscSubcomm   psubcomm   = NULL;
10114   MPI_Comm       subcomm_in = subcomm;
10115   Mat           *matseq;
10116   IS             isrow, iscol;
10117   PetscBool      newsubcomm = PETSC_FALSE;
10118 
10119   PetscFunctionBegin;
10120   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10121   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10122     PetscValidPointer(*matredundant, 5);
10123     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10124   }
10125 
10126   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10127   if (size == 1 || nsubcomm == 1) {
10128     if (reuse == MAT_INITIAL_MATRIX) {
10129       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10130     } else {
10131       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");
10132       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10133     }
10134     PetscFunctionReturn(0);
10135   }
10136 
10137   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10138   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10139   MatCheckPreallocated(mat, 1);
10140 
10141   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10142   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10143     /* create psubcomm, then get subcomm */
10144     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10145     PetscCallMPI(MPI_Comm_size(comm, &size));
10146     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10147 
10148     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10149     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10150     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10151     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10152     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10153     newsubcomm = PETSC_TRUE;
10154     PetscCall(PetscSubcommDestroy(&psubcomm));
10155   }
10156 
10157   /* get isrow, iscol and a local sequential matrix matseq[0] */
10158   if (reuse == MAT_INITIAL_MATRIX) {
10159     mloc_sub = PETSC_DECIDE;
10160     nloc_sub = PETSC_DECIDE;
10161     if (bs < 1) {
10162       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10163       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10164     } else {
10165       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10166       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10167     }
10168     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10169     rstart = rend - mloc_sub;
10170     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10171     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10172   } else { /* reuse == MAT_REUSE_MATRIX */
10173     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");
10174     /* retrieve subcomm */
10175     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10176     redund = (*matredundant)->redundant;
10177     isrow  = redund->isrow;
10178     iscol  = redund->iscol;
10179     matseq = redund->matseq;
10180   }
10181   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10182 
10183   /* get matredundant over subcomm */
10184   if (reuse == MAT_INITIAL_MATRIX) {
10185     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10186 
10187     /* create a supporting struct and attach it to C for reuse */
10188     PetscCall(PetscNew(&redund));
10189     (*matredundant)->redundant = redund;
10190     redund->isrow              = isrow;
10191     redund->iscol              = iscol;
10192     redund->matseq             = matseq;
10193     if (newsubcomm) {
10194       redund->subcomm = subcomm;
10195     } else {
10196       redund->subcomm = MPI_COMM_NULL;
10197     }
10198   } else {
10199     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10200   }
10201 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10202   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10203     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10204     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10205   }
10206 #endif
10207   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10208   PetscFunctionReturn(0);
10209 }
10210 
10211 /*@C
10212    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10213    a given `Mat`. Each submatrix can span multiple procs.
10214 
10215    Collective
10216 
10217    Input Parameters:
10218 +  mat - the matrix
10219 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10220 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10221 
10222    Output Parameter:
10223 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10224 
10225   Level: advanced
10226 
10227   Notes:
10228   The submatrix partition across processors is dictated by `subComm` a
10229   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10230   is not restricted to be grouped with consecutive original ranks.
10231 
10232   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10233   map directly to the layout of the original matrix [wrt the local
10234   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10235   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10236   the `subMat`. However the offDiagMat looses some columns - and this is
10237   reconstructed with `MatSetValues()`
10238 
10239   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10240 
10241 .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10242 @*/
10243 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10244 {
10245   PetscMPIInt commsize, subCommSize;
10246 
10247   PetscFunctionBegin;
10248   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10249   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10250   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10251 
10252   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");
10253   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10254   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10255   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10256   PetscFunctionReturn(0);
10257 }
10258 
10259 /*@
10260    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10261 
10262    Not Collective
10263 
10264    Input Parameters:
10265 +  mat - matrix to extract local submatrix from
10266 .  isrow - local row indices for submatrix
10267 -  iscol - local column indices for submatrix
10268 
10269    Output Parameter:
10270 .  submat - the submatrix
10271 
10272    Level: intermediate
10273 
10274    Notes:
10275    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10276 
10277    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10278    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10279 
10280    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10281    `MatSetValuesBlockedLocal()` will also be implemented.
10282 
10283    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10284    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10285 
10286 .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10287 @*/
10288 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10289 {
10290   PetscFunctionBegin;
10291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10292   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10293   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10294   PetscCheckSameComm(isrow, 2, iscol, 3);
10295   PetscValidPointer(submat, 4);
10296   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10297 
10298   if (mat->ops->getlocalsubmatrix) {
10299     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10300   } else {
10301     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10302   }
10303   PetscFunctionReturn(0);
10304 }
10305 
10306 /*@
10307    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10308 
10309    Not Collective
10310 
10311    Input Parameters:
10312 +  mat - matrix to extract local submatrix from
10313 .  isrow - local row indices for submatrix
10314 .  iscol - local column indices for submatrix
10315 -  submat - the submatrix
10316 
10317    Level: intermediate
10318 
10319 .seealso: `Mat`, `MatGetLocalSubMatrix()`
10320 @*/
10321 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10322 {
10323   PetscFunctionBegin;
10324   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10325   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10326   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10327   PetscCheckSameComm(isrow, 2, iscol, 3);
10328   PetscValidPointer(submat, 4);
10329   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10330 
10331   if (mat->ops->restorelocalsubmatrix) {
10332     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10333   } else {
10334     PetscCall(MatDestroy(submat));
10335   }
10336   *submat = NULL;
10337   PetscFunctionReturn(0);
10338 }
10339 
10340 /*@
10341    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10342 
10343    Collective
10344 
10345    Input Parameter:
10346 .  mat - the matrix
10347 
10348    Output Parameter:
10349 .  is - if any rows have zero diagonals this contains the list of them
10350 
10351    Level: developer
10352 
10353 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10354 @*/
10355 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10356 {
10357   PetscFunctionBegin;
10358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10359   PetscValidType(mat, 1);
10360   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10361   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10362 
10363   if (!mat->ops->findzerodiagonals) {
10364     Vec                diag;
10365     const PetscScalar *a;
10366     PetscInt          *rows;
10367     PetscInt           rStart, rEnd, r, nrow = 0;
10368 
10369     PetscCall(MatCreateVecs(mat, &diag, NULL));
10370     PetscCall(MatGetDiagonal(mat, diag));
10371     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10372     PetscCall(VecGetArrayRead(diag, &a));
10373     for (r = 0; r < rEnd - rStart; ++r)
10374       if (a[r] == 0.0) ++nrow;
10375     PetscCall(PetscMalloc1(nrow, &rows));
10376     nrow = 0;
10377     for (r = 0; r < rEnd - rStart; ++r)
10378       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10379     PetscCall(VecRestoreArrayRead(diag, &a));
10380     PetscCall(VecDestroy(&diag));
10381     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10382   } else {
10383     PetscUseTypeMethod(mat, findzerodiagonals, is);
10384   }
10385   PetscFunctionReturn(0);
10386 }
10387 
10388 /*@
10389    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10390 
10391    Collective
10392 
10393    Input Parameter:
10394 .  mat - the matrix
10395 
10396    Output Parameter:
10397 .  is - contains the list of rows with off block diagonal entries
10398 
10399    Level: developer
10400 
10401 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10402 @*/
10403 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10404 {
10405   PetscFunctionBegin;
10406   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10407   PetscValidType(mat, 1);
10408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10409   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10410 
10411   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10412   PetscFunctionReturn(0);
10413 }
10414 
10415 /*@C
10416   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10417 
10418   Collective; No Fortran Support
10419 
10420   Input Parameters:
10421 . mat - the matrix
10422 
10423   Output Parameters:
10424 . values - the block inverses in column major order (FORTRAN-like)
10425 
10426   Level: advanced
10427 
10428    Notes:
10429    The size of the blocks is determined by the block size of the matrix.
10430 
10431    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10432 
10433    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10434 
10435 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10436 @*/
10437 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10438 {
10439   PetscFunctionBegin;
10440   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10441   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10442   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10443   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10444   PetscFunctionReturn(0);
10445 }
10446 
10447 /*@C
10448   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10449 
10450   Collective; No Fortran Support
10451 
10452   Input Parameters:
10453 + mat - the matrix
10454 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10455 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10456 
10457   Output Parameters:
10458 . values - the block inverses in column major order (FORTRAN-like)
10459 
10460   Level: advanced
10461 
10462   Notes:
10463   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10464 
10465   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10466 
10467 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10468 @*/
10469 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10470 {
10471   PetscFunctionBegin;
10472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10473   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10474   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10475   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10476   PetscFunctionReturn(0);
10477 }
10478 
10479 /*@
10480   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10481 
10482   Collective on Mat
10483 
10484   Input Parameters:
10485 + A - the matrix
10486 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10487 
10488   Level: advanced
10489 
10490   Note:
10491   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10492 
10493 .seealso: `Mat`, `MatInvertBlockDiagonal()`
10494 @*/
10495 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10496 {
10497   const PetscScalar *vals;
10498   PetscInt          *dnnz;
10499   PetscInt           m, rstart, rend, bs, i, j;
10500 
10501   PetscFunctionBegin;
10502   PetscCall(MatInvertBlockDiagonal(A, &vals));
10503   PetscCall(MatGetBlockSize(A, &bs));
10504   PetscCall(MatGetLocalSize(A, &m, NULL));
10505   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10506   PetscCall(PetscMalloc1(m / bs, &dnnz));
10507   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10508   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10509   PetscCall(PetscFree(dnnz));
10510   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10511   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10512   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10513   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10514   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10515   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10516   PetscFunctionReturn(0);
10517 }
10518 
10519 /*@C
10520     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10521     via `MatTransposeColoringCreate()`.
10522 
10523     Collective on c
10524 
10525     Input Parameter:
10526 .   c - coloring context
10527 
10528     Level: intermediate
10529 
10530 .seealso: `Mat`, `MatTransposeColoringCreate()`
10531 @*/
10532 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10533 {
10534   MatTransposeColoring matcolor = *c;
10535 
10536   PetscFunctionBegin;
10537   if (!matcolor) PetscFunctionReturn(0);
10538   if (--((PetscObject)matcolor)->refct > 0) {
10539     matcolor = NULL;
10540     PetscFunctionReturn(0);
10541   }
10542 
10543   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10544   PetscCall(PetscFree(matcolor->rows));
10545   PetscCall(PetscFree(matcolor->den2sp));
10546   PetscCall(PetscFree(matcolor->colorforcol));
10547   PetscCall(PetscFree(matcolor->columns));
10548   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10549   PetscCall(PetscHeaderDestroy(c));
10550   PetscFunctionReturn(0);
10551 }
10552 
10553 /*@C
10554     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10555     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10556     `MatTransposeColoring` to sparse B.
10557 
10558     Collective on coloring
10559 
10560     Input Parameters:
10561 +   B - sparse matrix B
10562 .   Btdense - symbolic dense matrix B^T
10563 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10564 
10565     Output Parameter:
10566 .   Btdense - dense matrix B^T
10567 
10568     Level: developer
10569 
10570     Note:
10571     These are used internally for some implementations of `MatRARt()`
10572 
10573 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10574 @*/
10575 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10576 {
10577   PetscFunctionBegin;
10578   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10579   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10580   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10581 
10582   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10583   PetscFunctionReturn(0);
10584 }
10585 
10586 /*@C
10587     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10588     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10589     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10590     Csp from Cden.
10591 
10592     Collective
10593 
10594     Input Parameters:
10595 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10596 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10597 
10598     Output Parameter:
10599 .   Csp - sparse matrix
10600 
10601     Level: developer
10602 
10603     Note:
10604     These are used internally for some implementations of `MatRARt()`
10605 
10606 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10607 @*/
10608 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10609 {
10610   PetscFunctionBegin;
10611   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10612   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10613   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10614 
10615   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10616   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10617   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10618   PetscFunctionReturn(0);
10619 }
10620 
10621 /*@C
10622    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10623 
10624    Collective
10625 
10626    Input Parameters:
10627 +  mat - the matrix product C
10628 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10629 
10630     Output Parameter:
10631 .   color - the new coloring context
10632 
10633     Level: intermediate
10634 
10635 .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10636           `MatTransColoringApplyDenToSp()`
10637 @*/
10638 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10639 {
10640   MatTransposeColoring c;
10641   MPI_Comm             comm;
10642 
10643   PetscFunctionBegin;
10644   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10645   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10646   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10647 
10648   c->ctype = iscoloring->ctype;
10649   if (mat->ops->transposecoloringcreate) {
10650     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10651   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10652 
10653   *color = c;
10654   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10655   PetscFunctionReturn(0);
10656 }
10657 
10658 /*@
10659       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10660         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10661         same, otherwise it will be larger
10662 
10663      Not Collective
10664 
10665   Input Parameter:
10666 .    A  - the matrix
10667 
10668   Output Parameter:
10669 .    state - the current state
10670 
10671   Level: intermediate
10672 
10673   Notes:
10674     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10675          different matrices
10676 
10677     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10678 
10679     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10680 
10681 .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10682 @*/
10683 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10684 {
10685   PetscFunctionBegin;
10686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10687   *state = mat->nonzerostate;
10688   PetscFunctionReturn(0);
10689 }
10690 
10691 /*@
10692       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10693                  matrices from each processor
10694 
10695     Collective
10696 
10697    Input Parameters:
10698 +    comm - the communicators the parallel matrix will live on
10699 .    seqmat - the input sequential matrices
10700 .    n - number of local columns (or `PETSC_DECIDE`)
10701 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10702 
10703    Output Parameter:
10704 .    mpimat - the parallel matrix generated
10705 
10706     Level: developer
10707 
10708    Note:
10709     The number of columns of the matrix in EACH processor MUST be the same.
10710 
10711 .seealso: `Mat`
10712 @*/
10713 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10714 {
10715   PetscMPIInt size;
10716 
10717   PetscFunctionBegin;
10718   PetscCallMPI(MPI_Comm_size(comm, &size));
10719   if (size == 1) {
10720     if (reuse == MAT_INITIAL_MATRIX) {
10721       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10722     } else {
10723       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10724     }
10725     PetscFunctionReturn(0);
10726   }
10727 
10728   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");
10729 
10730   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10731   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10732   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10733   PetscFunctionReturn(0);
10734 }
10735 
10736 /*@
10737      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10738 
10739     Collective
10740 
10741    Input Parameters:
10742 +    A   - the matrix to create subdomains from
10743 -    N   - requested number of subdomains
10744 
10745    Output Parameters:
10746 +    n   - number of subdomains resulting on this rank
10747 -    iss - `IS` list with indices of subdomains on this rank
10748 
10749     Level: advanced
10750 
10751     Note:
10752     The number of subdomains must be smaller than the communicator size
10753 
10754 .seealso: `Mat`, `IS`
10755 @*/
10756 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10757 {
10758   MPI_Comm    comm, subcomm;
10759   PetscMPIInt size, rank, color;
10760   PetscInt    rstart, rend, k;
10761 
10762   PetscFunctionBegin;
10763   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10764   PetscCallMPI(MPI_Comm_size(comm, &size));
10765   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10766   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);
10767   *n    = 1;
10768   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10769   color = rank / k;
10770   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10771   PetscCall(PetscMalloc1(1, iss));
10772   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10773   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10774   PetscCallMPI(MPI_Comm_free(&subcomm));
10775   PetscFunctionReturn(0);
10776 }
10777 
10778 /*@
10779    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10780 
10781    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10782    If they are not the same, uses `MatMatMatMult()`.
10783 
10784    Once the coarse grid problem is constructed, correct for interpolation operators
10785    that are not of full rank, which can legitimately happen in the case of non-nested
10786    geometric multigrid.
10787 
10788    Input Parameters:
10789 +  restrct - restriction operator
10790 .  dA - fine grid matrix
10791 .  interpolate - interpolation operator
10792 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10793 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10794 
10795    Output Parameters:
10796 .  A - the Galerkin coarse matrix
10797 
10798    Options Database Key:
10799 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10800 
10801    Level: developer
10802 
10803 .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()`
10804 @*/
10805 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10806 {
10807   IS  zerorows;
10808   Vec diag;
10809 
10810   PetscFunctionBegin;
10811   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10812   /* Construct the coarse grid matrix */
10813   if (interpolate == restrct) {
10814     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10815   } else {
10816     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10817   }
10818 
10819   /* If the interpolation matrix is not of full rank, A will have zero rows.
10820      This can legitimately happen in the case of non-nested geometric multigrid.
10821      In that event, we set the rows of the matrix to the rows of the identity,
10822      ignoring the equations (as the RHS will also be zero). */
10823 
10824   PetscCall(MatFindZeroRows(*A, &zerorows));
10825 
10826   if (zerorows != NULL) { /* if there are any zero rows */
10827     PetscCall(MatCreateVecs(*A, &diag, NULL));
10828     PetscCall(MatGetDiagonal(*A, diag));
10829     PetscCall(VecISSet(diag, zerorows, 1.0));
10830     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10831     PetscCall(VecDestroy(&diag));
10832     PetscCall(ISDestroy(&zerorows));
10833   }
10834   PetscFunctionReturn(0);
10835 }
10836 
10837 /*@C
10838     MatSetOperation - Allows user to set a matrix operation for any matrix type
10839 
10840    Logically Collective
10841 
10842     Input Parameters:
10843 +   mat - the matrix
10844 .   op - the name of the operation
10845 -   f - the function that provides the operation
10846 
10847    Level: developer
10848 
10849     Usage:
10850 .vb
10851   extern PetscErrorCode usermult(Mat, Vec, Vec);
10852 
10853   PetscCall(MatCreateXXX(comm, ..., &A));
10854   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10855 .ve
10856 
10857     Notes:
10858     See the file `include/petscmat.h` for a complete list of matrix
10859     operations, which all have the form MATOP_<OPERATION>, where
10860     <OPERATION> is the name (in all capital letters) of the
10861     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10862 
10863     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10864     sequence as the usual matrix interface routines, since they
10865     are intended to be accessed via the usual matrix interface
10866     routines, e.g.,
10867 .vb
10868   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10869 .ve
10870 
10871     In particular each function MUST return `PETSC_SUCCESS` on success and
10872     nonzero on failure.
10873 
10874     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10875 
10876 .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10877 @*/
10878 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10879 {
10880   PetscFunctionBegin;
10881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10882   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10883   (((void (**)(void))mat->ops)[op]) = f;
10884   PetscFunctionReturn(0);
10885 }
10886 
10887 /*@C
10888     MatGetOperation - Gets a matrix operation for any matrix type.
10889 
10890     Not Collective
10891 
10892     Input Parameters:
10893 +   mat - the matrix
10894 -   op - the name of the operation
10895 
10896     Output Parameter:
10897 .   f - the function that provides the operation
10898 
10899     Level: developer
10900 
10901     Usage:
10902 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10903 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10904 
10905     Notes:
10906     See the file include/petscmat.h for a complete list of matrix
10907     operations, which all have the form MATOP_<OPERATION>, where
10908     <OPERATION> is the name (in all capital letters) of the
10909     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10910 
10911     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10912 
10913 .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10914 @*/
10915 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10916 {
10917   PetscFunctionBegin;
10918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10919   *f = (((void (**)(void))mat->ops)[op]);
10920   PetscFunctionReturn(0);
10921 }
10922 
10923 /*@
10924     MatHasOperation - Determines whether the given matrix supports the particular operation.
10925 
10926    Not Collective
10927 
10928    Input Parameters:
10929 +  mat - the matrix
10930 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10931 
10932    Output Parameter:
10933 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10934 
10935    Level: advanced
10936 
10937    Note:
10938    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
10939 
10940 .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10941 @*/
10942 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10943 {
10944   PetscFunctionBegin;
10945   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10946   PetscValidBoolPointer(has, 3);
10947   if (mat->ops->hasoperation) {
10948     PetscUseTypeMethod(mat, hasoperation, op, has);
10949   } else {
10950     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10951     else {
10952       *has = PETSC_FALSE;
10953       if (op == MATOP_CREATE_SUBMATRIX) {
10954         PetscMPIInt size;
10955 
10956         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10957         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10958       }
10959     }
10960   }
10961   PetscFunctionReturn(0);
10962 }
10963 
10964 /*@
10965     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10966 
10967    Collective
10968 
10969    Input Parameters:
10970 .  mat - the matrix
10971 
10972    Output Parameter:
10973 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10974 
10975    Level: beginner
10976 
10977 .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10978 @*/
10979 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
10980 {
10981   PetscFunctionBegin;
10982   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10983   PetscValidType(mat, 1);
10984   PetscValidBoolPointer(cong, 2);
10985   if (!mat->rmap || !mat->cmap) {
10986     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10987     PetscFunctionReturn(0);
10988   }
10989   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10990     PetscCall(PetscLayoutSetUp(mat->rmap));
10991     PetscCall(PetscLayoutSetUp(mat->cmap));
10992     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10993     if (*cong) mat->congruentlayouts = 1;
10994     else mat->congruentlayouts = 0;
10995   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10996   PetscFunctionReturn(0);
10997 }
10998 
10999 PetscErrorCode MatSetInf(Mat A)
11000 {
11001   PetscFunctionBegin;
11002   PetscUseTypeMethod(A, setinf);
11003   PetscFunctionReturn(0);
11004 }
11005 
11006 /*C
11007    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
11008    and possibly removes small values from the graph structure.
11009 
11010    Collective
11011 
11012    Input Parameters:
11013 +  A - the matrix
11014 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11015 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11016 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11017 
11018    Output Parameter:
11019 .  graph - the resulting graph
11020 
11021    Level: advanced
11022 
11023 .seealso: `Mat`, `MatCreate()`, `PCGAMG`
11024 */
11025 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11026 {
11027   PetscFunctionBegin;
11028   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11029   PetscValidType(A, 1);
11030   PetscValidPointer(graph, 3);
11031   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11032   PetscFunctionReturn(0);
11033 }
11034