xref: /petsc/src/mat/interface/matrix.c (revision b4f8a55a69b2805e0b0c023bc6ec977a7834d796)
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_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_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
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   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72   for sparse matrices that already have locations it fills the locations with random numbers.
73 
74   It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
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   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
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: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
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: [](ch_matrices), `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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
250 }
251 
252 /*@
253   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 . mat - 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: [](ch_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscAssertPointer(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(PETSC_SUCCESS);
279 }
280 
281 /*@
282   MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 . mat - 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: [](ch_matrices), `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   PetscAssertPointer(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(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323   Not Collective
324 
325   Input Parameter:
326 . A - the matrix
327 
328   Output Parameter:
329 . a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331   Level: advanced
332 
333   Notes:
334   See `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: [](ch_matrices), `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   PetscAssertPointer(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(PETSC_SUCCESS);
356 }
357 
358 /*@
359   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361   Collective
362 
363   Input Parameter:
364 . mat - the matrix
365 
366   Output Parameter:
367 . trace - the sum of the diagonal entries
368 
369   Level: advanced
370 
371 .seealso: [](ch_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscAssertPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388   MatRealPart - Zeros out the imaginary part of the matrix
389 
390   Logically Collective
391 
392   Input Parameter:
393 . mat - the matrix
394 
395   Level: advanced
396 
397 .seealso: [](ch_matrices), `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(PETSC_SUCCESS);
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 (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: [](ch_matrices), `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(PETSC_SUCCESS);
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 Parameter:
451 . mat - the matrix
452 
453   Level: advanced
454 
455 .seealso: [](ch_matrices), `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(PETSC_SUCCESS);
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: [](ch_matrices), `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   PetscAssertPointer(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(PETSC_SUCCESS);
495 }
496 
497 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
498 /*@C
499   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
500   for each row that you get to ensure that your application does
501   not bleed memory.
502 
503   Not Collective
504 
505   Input Parameters:
506 + mat - the matrix
507 - row - the row to get
508 
509   Output Parameters:
510 + ncols - if not `NULL`, the number of nonzeros in the row
511 . cols  - if not `NULL`, the column numbers
512 - vals  - if not `NULL`, the values
513 
514   Level: advanced
515 
516   Notes:
517   This routine is provided for people who need to have direct access
518   to the structure of a matrix.  We hope that we provide enough
519   high-level matrix routines that few users will need it.
520 
521   `MatGetRow()` always returns 0-based column indices, regardless of
522   whether the internal representation is 0-based (default) or 1-based.
523 
524   For better efficiency, set cols and/or vals to `NULL` if you do
525   not wish to extract these quantities.
526 
527   The user can only examine the values extracted with `MatGetRow()`;
528   the values cannot be altered.  To change the matrix entries, one
529   must use `MatSetValues()`.
530 
531   You can only have one call to `MatGetRow()` outstanding for a particular
532   matrix at a time, per processor. `MatGetRow()` can only obtain rows
533   associated with the given processor, it cannot get rows from the
534   other processors; for that we suggest using `MatCreateSubMatrices()`, then
535   MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
536   is in the global number of rows.
537 
538   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
539 
540   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
541 
542   Fortran Notes:
543   The calling sequence is
544 .vb
545    MatGetRow(matrix,row,ncols,cols,values,ierr)
546          Mat     matrix (input)
547          integer row    (input)
548          integer ncols  (output)
549          integer cols(maxcols) (output)
550          double precision (or double complex) values(maxcols) output
551 .ve
552   where maxcols >= maximum nonzeros in any row of the matrix.
553 
554   Caution:
555   Do not try to change the contents of the output arrays (`cols` and `vals`).
556   In some cases, this may corrupt the matrix.
557 
558 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
559 @*/
560 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
561 {
562   PetscInt incols;
563 
564   PetscFunctionBegin;
565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
566   PetscValidType(mat, 1);
567   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
568   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
569   MatCheckPreallocated(mat, 1);
570   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);
571   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
572   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
573   if (ncols) *ncols = incols;
574   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
575   PetscFunctionReturn(PETSC_SUCCESS);
576 }
577 
578 /*@
579   MatConjugate - replaces the matrix values with their complex conjugates
580 
581   Logically Collective
582 
583   Input Parameter:
584 . mat - the matrix
585 
586   Level: advanced
587 
588 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
589 @*/
590 PetscErrorCode MatConjugate(Mat mat)
591 {
592   PetscFunctionBegin;
593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
594   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
595   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
596     PetscUseTypeMethod(mat, conjugate);
597     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
598   }
599   PetscFunctionReturn(PETSC_SUCCESS);
600 }
601 
602 /*@C
603   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
604 
605   Not Collective
606 
607   Input Parameters:
608 + mat   - the matrix
609 . row   - the row to get
610 . ncols - the number of nonzeros
611 . cols  - the columns of the nonzeros
612 - vals  - if nonzero the column values
613 
614   Level: advanced
615 
616   Notes:
617   This routine should be called after you have finished examining the entries.
618 
619   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
620   us of the array after it has been restored. If you pass `NULL`, it will
621   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
622 
623   Fortran Notes:
624   The calling sequence is
625 .vb
626    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
627       Mat     matrix (input)
628       integer row    (input)
629       integer ncols  (output)
630       integer cols(maxcols) (output)
631       double precision (or double complex) values(maxcols) output
632 .ve
633   Where maxcols >= maximum nonzeros in any row of the matrix.
634 
635   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
636   before another call to `MatGetRow()` can be made.
637 
638 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
639 @*/
640 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
641 {
642   PetscFunctionBegin;
643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
644   if (ncols) PetscAssertPointer(ncols, 3);
645   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
646   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
647   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
648   if (ncols) *ncols = 0;
649   if (cols) *cols = NULL;
650   if (vals) *vals = NULL;
651   PetscFunctionReturn(PETSC_SUCCESS);
652 }
653 
654 /*@
655   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
656   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
657 
658   Not Collective
659 
660   Input Parameter:
661 . mat - the matrix
662 
663   Level: advanced
664 
665   Note:
666   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.
667 
668 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
669 @*/
670 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
671 {
672   PetscFunctionBegin;
673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
674   PetscValidType(mat, 1);
675   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
676   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
677   MatCheckPreallocated(mat, 1);
678   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
679   PetscUseTypeMethod(mat, getrowuppertriangular);
680   PetscFunctionReturn(PETSC_SUCCESS);
681 }
682 
683 /*@
684   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
685 
686   Not Collective
687 
688   Input Parameter:
689 . mat - the matrix
690 
691   Level: advanced
692 
693   Note:
694   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
695 
696 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
697 @*/
698 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
699 {
700   PetscFunctionBegin;
701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
702   PetscValidType(mat, 1);
703   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
704   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
705   MatCheckPreallocated(mat, 1);
706   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
707   PetscUseTypeMethod(mat, restorerowuppertriangular);
708   PetscFunctionReturn(PETSC_SUCCESS);
709 }
710 
711 /*@C
712   MatSetOptionsPrefix - Sets the prefix used for searching for all
713   `Mat` options in the database.
714 
715   Logically Collective
716 
717   Input Parameters:
718 + A      - the matrix
719 - prefix - the prefix to prepend to all option names
720 
721   Level: advanced
722 
723   Notes:
724   A hyphen (-) must NOT be given at the beginning of the prefix name.
725   The first character of all runtime options is AUTOMATICALLY the hyphen.
726 
727   This is NOT used for options for the factorization of the matrix. Normally the
728   prefix is automatically passed in from the PC calling the factorization. To set
729   it directly use  `MatSetOptionsPrefixFactor()`
730 
731 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
732 @*/
733 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
734 {
735   PetscFunctionBegin;
736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
737   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
738   PetscFunctionReturn(PETSC_SUCCESS);
739 }
740 
741 /*@C
742   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
743   for matrices created with `MatGetFactor()`
744 
745   Logically Collective
746 
747   Input Parameters:
748 + A      - the matrix
749 - prefix - the prefix to prepend to all option names for the factored matrix
750 
751   Level: developer
752 
753   Notes:
754   A hyphen (-) must NOT be given at the beginning of the prefix name.
755   The first character of all runtime options is AUTOMATICALLY the hyphen.
756 
757   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
758   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
759 
760 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
761 @*/
762 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
763 {
764   PetscFunctionBegin;
765   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
766   if (prefix) {
767     PetscAssertPointer(prefix, 2);
768     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
769     if (prefix != A->factorprefix) {
770       PetscCall(PetscFree(A->factorprefix));
771       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
772     }
773   } else PetscCall(PetscFree(A->factorprefix));
774   PetscFunctionReturn(PETSC_SUCCESS);
775 }
776 
777 /*@C
778   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
779   for matrices created with `MatGetFactor()`
780 
781   Logically Collective
782 
783   Input Parameters:
784 + A      - the matrix
785 - prefix - the prefix to prepend to all option names for the factored matrix
786 
787   Level: developer
788 
789   Notes:
790   A hyphen (-) must NOT be given at the beginning of the prefix name.
791   The first character of all runtime options is AUTOMATICALLY the hyphen.
792 
793   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
794   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
795 
796 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
797           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
798           `MatSetOptionsPrefix()`
799 @*/
800 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
801 {
802   size_t len1, len2, new_len;
803 
804   PetscFunctionBegin;
805   PetscValidHeader(A, 1);
806   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
807   if (!A->factorprefix) {
808     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
809     PetscFunctionReturn(PETSC_SUCCESS);
810   }
811   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
812 
813   PetscCall(PetscStrlen(A->factorprefix, &len1));
814   PetscCall(PetscStrlen(prefix, &len2));
815   new_len = len1 + len2 + 1;
816   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
817   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
818   PetscFunctionReturn(PETSC_SUCCESS);
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: [](ch_matrices), `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(PETSC_SUCCESS);
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 Notes:
862   The user should pass in a string `prefix` of
863   sufficient length to hold the prefix.
864 
865 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
866 @*/
867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
868 {
869   PetscFunctionBegin;
870   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
871   PetscAssertPointer(prefix, 2);
872   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
873   PetscFunctionReturn(PETSC_SUCCESS);
874 }
875 
876 /*@
877   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
878 
879   Collective
880 
881   Input Parameter:
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  `MATAIJ` matrices.
892 
893 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
894 @*/
895 PetscErrorCode MatResetPreallocation(Mat A)
896 {
897   PetscFunctionBegin;
898   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
899   PetscValidType(A, 1);
900   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
901   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
902   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
903   PetscFunctionReturn(PETSC_SUCCESS);
904 }
905 
906 /*@
907   MatSetUp - Sets up the internal matrix data structures for later use.
908 
909   Collective
910 
911   Input Parameter:
912 . A - the matrix
913 
914   Level: intermediate
915 
916   Notes:
917   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
918   setting values in the matrix.
919 
920   If a suitable preallocation routine is used, this function does not need to be called.
921 
922   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
923 
924 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
925 @*/
926 PetscErrorCode MatSetUp(Mat A)
927 {
928   PetscFunctionBegin;
929   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
930   if (!((PetscObject)A)->type_name) {
931     PetscMPIInt size;
932 
933     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
934     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
935   }
936   if (!A->preallocated) PetscTryTypeMethod(A, setup);
937   PetscCall(PetscLayoutSetUp(A->rmap));
938   PetscCall(PetscLayoutSetUp(A->cmap));
939   A->preallocated = PETSC_TRUE;
940   PetscFunctionReturn(PETSC_SUCCESS);
941 }
942 
943 #if defined(PETSC_HAVE_SAWS)
944   #include <petscviewersaws.h>
945 #endif
946 
947 /*
948    If threadsafety is on extraneous matrices may be printed
949 
950    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
951 */
952 #if !defined(PETSC_HAVE_THREADSAFETY)
953 static PetscInt insidematview = 0;
954 #endif
955 
956 /*@C
957   MatViewFromOptions - View properties of the matrix based on options set in the options database
958 
959   Collective
960 
961   Input Parameters:
962 + A    - the matrix
963 . obj  - optional additional object that provides the options prefix to use
964 - name - command line option
965 
966   Options Database Key:
967 . -mat_view [viewertype]:... - the viewer and its options
968 
969   Level: intermediate
970 
971   Notes:
972 .vb
973     If no value is provided ascii:stdout is used
974        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
975                                                   for example ascii::ascii_info prints just the information about the object not all details
976                                                   unless :append is given filename opens in write mode, overwriting what was already there
977        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
978        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
979        socket[:port]                             defaults to the standard output port
980        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
981 .ve
982 
983 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
984 @*/
985 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
986 {
987   PetscFunctionBegin;
988   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
989 #if !defined(PETSC_HAVE_THREADSAFETY)
990   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
991 #endif
992   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
993   PetscFunctionReturn(PETSC_SUCCESS);
994 }
995 
996 /*@C
997   MatView - display information about a matrix in a variety ways
998 
999   Collective
1000 
1001   Input Parameters:
1002 + mat    - the matrix
1003 - viewer - visualization context
1004 
1005   Options Database Keys:
1006 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1007 . -mat_view ::ascii_info_detail    - Prints more detailed info
1008 . -mat_view                        - Prints matrix in ASCII format
1009 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1010 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1011 . -display <name>                  - Sets display name (default is host)
1012 . -draw_pause <sec>                - Sets number of seconds to pause after display
1013 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1014 . -viewer_socket_machine <machine> - -
1015 . -viewer_socket_port <port>       - -
1016 . -mat_view binary                 - save matrix to file in binary format
1017 - -viewer_binary_filename <name>   - -
1018 
1019   Level: beginner
1020 
1021   Notes:
1022   The available visualization contexts include
1023 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1024 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1025 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1026 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1027 
1028   The user can open alternative visualization contexts with
1029 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1030 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1031   specified file; corresponding input uses `MatLoad()`
1032 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1033   an X window display
1034 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1035   Currently only the `MATSEQDENSE` and `MATAIJ`
1036   matrix types support the Socket viewer.
1037 
1038   The user can call `PetscViewerPushFormat()` to specify the output
1039   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1040   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1041 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1042 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1043 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1044 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1045   format common among all matrix types
1046 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1047   format (which is in many cases the same as the default)
1048 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1049   size and structure (not the matrix entries)
1050 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1051   the matrix structure
1052 
1053   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1054   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1055 
1056   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1057 
1058   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1059   viewer is used.
1060 
1061   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1062   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1063 
1064   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1065   and then use the following mouse functions.
1066 .vb
1067   left mouse: zoom in
1068   middle mouse: zoom out
1069   right mouse: continue with the simulation
1070 .ve
1071 
1072 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1073           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1074 @*/
1075 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1076 {
1077   PetscInt          rows, cols, rbs, cbs;
1078   PetscBool         isascii, isstring, issaws;
1079   PetscViewerFormat format;
1080   PetscMPIInt       size;
1081 
1082   PetscFunctionBegin;
1083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1084   PetscValidType(mat, 1);
1085   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1086   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1087   PetscCheckSameComm(mat, 1, viewer, 2);
1088 
1089   PetscCall(PetscViewerGetFormat(viewer, &format));
1090   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1091   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1092 
1093 #if !defined(PETSC_HAVE_THREADSAFETY)
1094   insidematview++;
1095 #endif
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1098   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1099   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");
1100 
1101   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1102   if (isascii) {
1103     if (!mat->preallocated) {
1104       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1105 #if !defined(PETSC_HAVE_THREADSAFETY)
1106       insidematview--;
1107 #endif
1108       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1109       PetscFunctionReturn(PETSC_SUCCESS);
1110     }
1111     if (!mat->assembled) {
1112       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1113 #if !defined(PETSC_HAVE_THREADSAFETY)
1114       insidematview--;
1115 #endif
1116       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1117       PetscFunctionReturn(PETSC_SUCCESS);
1118     }
1119     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1120     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1121       MatNullSpace nullsp, transnullsp;
1122 
1123       PetscCall(PetscViewerASCIIPushTab(viewer));
1124       PetscCall(MatGetSize(mat, &rows, &cols));
1125       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1126       if (rbs != 1 || cbs != 1) {
1127         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1128         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1129       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1130       if (mat->factortype) {
1131         MatSolverType solver;
1132         PetscCall(MatFactorGetSolverType(mat, &solver));
1133         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1134       }
1135       if (mat->ops->getinfo) {
1136         MatInfo info;
1137         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1138         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1139         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1140       }
1141       PetscCall(MatGetNullSpace(mat, &nullsp));
1142       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1143       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1144       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1145       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1146       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1147       PetscCall(PetscViewerASCIIPushTab(viewer));
1148       PetscCall(MatProductView(mat, viewer));
1149       PetscCall(PetscViewerASCIIPopTab(viewer));
1150     }
1151   } else if (issaws) {
1152 #if defined(PETSC_HAVE_SAWS)
1153     PetscMPIInt rank;
1154 
1155     PetscCall(PetscObjectName((PetscObject)mat));
1156     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1157     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1158 #endif
1159   } else if (isstring) {
1160     const char *type;
1161     PetscCall(MatGetType(mat, &type));
1162     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1163     PetscTryTypeMethod(mat, view, viewer);
1164   }
1165   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1166     PetscCall(PetscViewerASCIIPushTab(viewer));
1167     PetscUseTypeMethod(mat, viewnative, viewer);
1168     PetscCall(PetscViewerASCIIPopTab(viewer));
1169   } else if (mat->ops->view) {
1170     PetscCall(PetscViewerASCIIPushTab(viewer));
1171     PetscUseTypeMethod(mat, view, viewer);
1172     PetscCall(PetscViewerASCIIPopTab(viewer));
1173   }
1174   if (isascii) {
1175     PetscCall(PetscViewerGetFormat(viewer, &format));
1176     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1177   }
1178   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1179 #if !defined(PETSC_HAVE_THREADSAFETY)
1180   insidematview--;
1181 #endif
1182   PetscFunctionReturn(PETSC_SUCCESS);
1183 }
1184 
1185 #if defined(PETSC_USE_DEBUG)
1186   #include <../src/sys/totalview/tv_data_display.h>
1187 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1188 {
1189   TV_add_row("Local rows", "int", &mat->rmap->n);
1190   TV_add_row("Local columns", "int", &mat->cmap->n);
1191   TV_add_row("Global rows", "int", &mat->rmap->N);
1192   TV_add_row("Global columns", "int", &mat->cmap->N);
1193   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1194   return TV_format_OK;
1195 }
1196 #endif
1197 
1198 /*@C
1199   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1200   with `MatView()`.  The matrix format is determined from the options database.
1201   Generates a parallel MPI matrix if the communicator has more than one
1202   processor.  The default matrix type is `MATAIJ`.
1203 
1204   Collective
1205 
1206   Input Parameters:
1207 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1208             or some related function before a call to `MatLoad()`
1209 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1210 
1211   Options Database Keys:
1212    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1213    block size
1214 . -matload_block_size <bs> - set block size
1215 
1216   Level: beginner
1217 
1218   Notes:
1219   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1220   `Mat` before calling this routine if you wish to set it from the options database.
1221 
1222   `MatLoad()` automatically loads into the options database any options
1223   given in the file filename.info where filename is the name of the file
1224   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1225   file will be ignored if you use the -viewer_binary_skip_info option.
1226 
1227   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1228   sets the default matrix type AIJ and sets the local and global sizes.
1229   If type and/or size is already set, then the same are used.
1230 
1231   In parallel, each processor can load a subset of rows (or the
1232   entire matrix).  This routine is especially useful when a large
1233   matrix is stored on disk and only part of it is desired on each
1234   processor.  For example, a parallel solver may access only some of
1235   the rows from each processor.  The algorithm used here reads
1236   relatively small blocks of data rather than reading the entire
1237   matrix and then subsetting it.
1238 
1239   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1240   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1241   or the sequence like
1242 .vb
1243     `PetscViewer` v;
1244     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1245     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1246     `PetscViewerSetFromOptions`(v);
1247     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1248     `PetscViewerFileSetName`(v,"datafile");
1249 .ve
1250   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1251 $ -viewer_type {binary, hdf5}
1252 
1253   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1254   and src/mat/tutorials/ex10.c with the second approach.
1255 
1256   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1257   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1258   Multiple objects, both matrices and vectors, can be stored within the same file.
1259   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1260 
1261   Most users should not need to know the details of the binary storage
1262   format, since `MatLoad()` and `MatView()` completely hide these details.
1263   But for anyone who is interested, the standard binary matrix storage
1264   format is
1265 
1266 .vb
1267     PetscInt    MAT_FILE_CLASSID
1268     PetscInt    number of rows
1269     PetscInt    number of columns
1270     PetscInt    total number of nonzeros
1271     PetscInt    *number nonzeros in each row
1272     PetscInt    *column indices of all nonzeros (starting index is zero)
1273     PetscScalar *values of all nonzeros
1274 .ve
1275   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1276   stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1277   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1278 
1279   PETSc automatically does the byte swapping for
1280   machines that store the bytes reversed. Thus if you write your own binary
1281   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1282   and `PetscBinaryWrite()` to see how this may be done.
1283 
1284   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1285   Each processor's chunk is loaded independently by its owning MPI process.
1286   Multiple objects, both matrices and vectors, can be stored within the same file.
1287   They are looked up by their PetscObject name.
1288 
1289   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1290   by default the same structure and naming of the AIJ arrays and column count
1291   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1292 $    save example.mat A b -v7.3
1293   can be directly read by this routine (see Reference 1 for details).
1294 
1295   Depending on your MATLAB version, this format might be a default,
1296   otherwise you can set it as default in Preferences.
1297 
1298   Unless -nocompression flag is used to save the file in MATLAB,
1299   PETSc must be configured with ZLIB package.
1300 
1301   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1302 
1303   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1304 
1305   Corresponding `MatView()` is not yet implemented.
1306 
1307   The loaded matrix is actually a transpose of the original one in MATLAB,
1308   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1309   With this format, matrix is automatically transposed by PETSc,
1310   unless the matrix is marked as SPD or symmetric
1311   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1312 
1313   References:
1314 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1315 
1316 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1317  @*/
1318 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1319 {
1320   PetscBool flg;
1321 
1322   PetscFunctionBegin;
1323   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1324   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1325 
1326   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1327 
1328   flg = PETSC_FALSE;
1329   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1330   if (flg) {
1331     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1332     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1333   }
1334   flg = PETSC_FALSE;
1335   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1336   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1337 
1338   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1339   PetscUseTypeMethod(mat, load, viewer);
1340   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1341   PetscFunctionReturn(PETSC_SUCCESS);
1342 }
1343 
1344 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1345 {
1346   Mat_Redundant *redund = *redundant;
1347 
1348   PetscFunctionBegin;
1349   if (redund) {
1350     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1351       PetscCall(ISDestroy(&redund->isrow));
1352       PetscCall(ISDestroy(&redund->iscol));
1353       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1354     } else {
1355       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1356       PetscCall(PetscFree(redund->sbuf_j));
1357       PetscCall(PetscFree(redund->sbuf_a));
1358       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1359         PetscCall(PetscFree(redund->rbuf_j[i]));
1360         PetscCall(PetscFree(redund->rbuf_a[i]));
1361       }
1362       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1363     }
1364 
1365     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1366     PetscCall(PetscFree(redund));
1367   }
1368   PetscFunctionReturn(PETSC_SUCCESS);
1369 }
1370 
1371 /*@C
1372   MatDestroy - Frees space taken by a matrix.
1373 
1374   Collective
1375 
1376   Input Parameter:
1377 . A - the matrix
1378 
1379   Level: beginner
1380 
1381   Developer Notes:
1382   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1383   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1384   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1385   if changes are needed here.
1386 
1387 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1388 @*/
1389 PetscErrorCode MatDestroy(Mat *A)
1390 {
1391   PetscFunctionBegin;
1392   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1393   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1394   if (--((PetscObject)(*A))->refct > 0) {
1395     *A = NULL;
1396     PetscFunctionReturn(PETSC_SUCCESS);
1397   }
1398 
1399   /* if memory was published with SAWs then destroy it */
1400   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1401   PetscTryTypeMethod((*A), destroy);
1402 
1403   PetscCall(PetscFree((*A)->factorprefix));
1404   PetscCall(PetscFree((*A)->defaultvectype));
1405   PetscCall(PetscFree((*A)->defaultrandtype));
1406   PetscCall(PetscFree((*A)->bsizes));
1407   PetscCall(PetscFree((*A)->solvertype));
1408   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1409   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1410   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1411   PetscCall(MatProductClear(*A));
1412   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1413   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1414   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1415   PetscCall(MatDestroy(&(*A)->schur));
1416   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1417   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1418   PetscCall(PetscHeaderDestroy(A));
1419   PetscFunctionReturn(PETSC_SUCCESS);
1420 }
1421 
1422 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1423 /*@C
1424   MatSetValues - Inserts or adds a block of values into a matrix.
1425   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1426   MUST be called after all calls to `MatSetValues()` have been completed.
1427 
1428   Not Collective
1429 
1430   Input Parameters:
1431 + mat  - the matrix
1432 . v    - a logically two-dimensional array of values
1433 . m    - the number of rows
1434 . idxm - the global indices of the rows
1435 . n    - the number of columns
1436 . idxn - the global indices of the columns
1437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1438 
1439   Level: beginner
1440 
1441   Notes:
1442   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1443 
1444   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1445   options cannot be mixed without intervening calls to the assembly
1446   routines.
1447 
1448   `MatSetValues()` uses 0-based row and column numbers in Fortran
1449   as well as in C.
1450 
1451   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1452   simply ignored. This allows easily inserting element stiffness matrices
1453   with homogeneous Dirichlet boundary conditions that you don't want represented
1454   in the matrix.
1455 
1456   Efficiency Alert:
1457   The routine `MatSetValuesBlocked()` may offer much better efficiency
1458   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1459 
1460   Developer Notes:
1461   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1462   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1463 
1464 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1465           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1466 @*/
1467 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1468 {
1469   PetscFunctionBeginHot;
1470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1471   PetscValidType(mat, 1);
1472   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1473   PetscAssertPointer(idxm, 3);
1474   PetscAssertPointer(idxn, 5);
1475   MatCheckPreallocated(mat, 1);
1476 
1477   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1478   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1479 
1480   if (PetscDefined(USE_DEBUG)) {
1481     PetscInt i, j;
1482 
1483     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1484     for (i = 0; i < m; i++) {
1485       for (j = 0; j < n; j++) {
1486         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1487 #if defined(PETSC_USE_COMPLEX)
1488           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]);
1489 #else
1490           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]);
1491 #endif
1492       }
1493     }
1494     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);
1495     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);
1496   }
1497 
1498   if (mat->assembled) {
1499     mat->was_assembled = PETSC_TRUE;
1500     mat->assembled     = PETSC_FALSE;
1501   }
1502   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1503   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1504   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1505   PetscFunctionReturn(PETSC_SUCCESS);
1506 }
1507 
1508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1509 /*@C
1510   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1511   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1512   MUST be called after all calls to `MatSetValues()` have been completed.
1513 
1514   Not Collective
1515 
1516   Input Parameters:
1517 + mat  - the matrix
1518 . v    - a logically two-dimensional array of values
1519 . ism  - the rows to provide
1520 . isn  - the columns to provide
1521 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1522 
1523   Level: beginner
1524 
1525   Notes:
1526   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1527 
1528   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1529   options cannot be mixed without intervening calls to the assembly
1530   routines.
1531 
1532   `MatSetValues()` uses 0-based row and column numbers in Fortran
1533   as well as in C.
1534 
1535   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1536   simply ignored. This allows easily inserting element stiffness matrices
1537   with homogeneous Dirichlet boundary conditions that you don't want represented
1538   in the matrix.
1539 
1540   Efficiency Alert:
1541   The routine `MatSetValuesBlocked()` may offer much better efficiency
1542   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1543 
1544   This is currently not optimized for any particular `ISType`
1545 
1546   Developer Notes:
1547   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1548   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1549 
1550 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1551           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1552 @*/
1553 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1554 {
1555   PetscInt        m, n;
1556   const PetscInt *rows, *cols;
1557 
1558   PetscFunctionBeginHot;
1559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1560   PetscCall(ISGetIndices(ism, &rows));
1561   PetscCall(ISGetIndices(isn, &cols));
1562   PetscCall(ISGetLocalSize(ism, &m));
1563   PetscCall(ISGetLocalSize(isn, &n));
1564   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1565   PetscCall(ISRestoreIndices(ism, &rows));
1566   PetscCall(ISRestoreIndices(isn, &cols));
1567   PetscFunctionReturn(PETSC_SUCCESS);
1568 }
1569 
1570 /*@
1571   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1572   values into a matrix
1573 
1574   Not Collective
1575 
1576   Input Parameters:
1577 + mat - the matrix
1578 . row - the (block) row to set
1579 - v   - a logically two-dimensional array of values
1580 
1581   Level: intermediate
1582 
1583   Notes:
1584   The values, `v`, are column-oriented (for the block version) and sorted
1585 
1586   All the nonzeros in the row must be provided
1587 
1588   The matrix must have previously had its column indices set, likely by having been assembled.
1589 
1590   The row must belong to this process
1591 
1592 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1593           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1594 @*/
1595 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1596 {
1597   PetscInt globalrow;
1598 
1599   PetscFunctionBegin;
1600   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1601   PetscValidType(mat, 1);
1602   PetscAssertPointer(v, 3);
1603   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1604   PetscCall(MatSetValuesRow(mat, globalrow, v));
1605   PetscFunctionReturn(PETSC_SUCCESS);
1606 }
1607 
1608 /*@
1609   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1610   values into a matrix
1611 
1612   Not Collective
1613 
1614   Input Parameters:
1615 + mat - the matrix
1616 . row - the (block) row to set
1617 - 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
1618 
1619   Level: advanced
1620 
1621   Notes:
1622   The values, `v`, are column-oriented for the block version.
1623 
1624   All the nonzeros in the row must be provided
1625 
1626   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1627 
1628   The row must belong to this process
1629 
1630 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1631           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1632 @*/
1633 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1634 {
1635   PetscFunctionBeginHot;
1636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1637   PetscValidType(mat, 1);
1638   MatCheckPreallocated(mat, 1);
1639   PetscAssertPointer(v, 3);
1640   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1641   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1642   mat->insertmode = INSERT_VALUES;
1643 
1644   if (mat->assembled) {
1645     mat->was_assembled = PETSC_TRUE;
1646     mat->assembled     = PETSC_FALSE;
1647   }
1648   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1649   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1650   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1651   PetscFunctionReturn(PETSC_SUCCESS);
1652 }
1653 
1654 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1655 /*@
1656   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1657   Using structured grid indexing
1658 
1659   Not Collective
1660 
1661   Input Parameters:
1662 + mat  - the matrix
1663 . m    - number of rows being entered
1664 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1665 . n    - number of columns being entered
1666 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1667 . v    - a logically two-dimensional array of values
1668 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1669 
1670   Level: beginner
1671 
1672   Notes:
1673   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1674 
1675   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1676   options cannot be mixed without intervening calls to the assembly
1677   routines.
1678 
1679   The grid coordinates are across the entire grid, not just the local portion
1680 
1681   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1682   as well as in C.
1683 
1684   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1685 
1686   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1687   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1688 
1689   The columns and rows in the stencil passed in MUST be contained within the
1690   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1691   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1692   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1693   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1694 
1695   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1696   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1697   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1698   `DM_BOUNDARY_PERIODIC` boundary type.
1699 
1700   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
1701   a single value per point) you can skip filling those indices.
1702 
1703   Inspired by the structured grid interface to the HYPRE package
1704   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1705 
1706   Efficiency Alert:
1707   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1708   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1709 
1710   Fortran Notes:
1711   `idxm` and `idxn` should be declared as
1712 $     MatStencil idxm(4,m),idxn(4,n)
1713   and the values inserted using
1714 .vb
1715     idxm(MatStencil_i,1) = i
1716     idxm(MatStencil_j,1) = j
1717     idxm(MatStencil_k,1) = k
1718     idxm(MatStencil_c,1) = c
1719     etc
1720 .ve
1721 
1722 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1723           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1724 @*/
1725 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1726 {
1727   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1728   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1729   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1730 
1731   PetscFunctionBegin;
1732   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1733   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1734   PetscValidType(mat, 1);
1735   PetscAssertPointer(idxm, 3);
1736   PetscAssertPointer(idxn, 5);
1737 
1738   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1739     jdxm = buf;
1740     jdxn = buf + m;
1741   } else {
1742     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1743     jdxm = bufm;
1744     jdxn = bufn;
1745   }
1746   for (i = 0; i < m; i++) {
1747     for (j = 0; j < 3 - sdim; j++) dxm++;
1748     tmp = *dxm++ - starts[0];
1749     for (j = 0; j < dim - 1; j++) {
1750       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1751       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1752     }
1753     if (mat->stencil.noc) dxm++;
1754     jdxm[i] = tmp;
1755   }
1756   for (i = 0; i < n; i++) {
1757     for (j = 0; j < 3 - sdim; j++) dxn++;
1758     tmp = *dxn++ - starts[0];
1759     for (j = 0; j < dim - 1; j++) {
1760       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1761       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1762     }
1763     if (mat->stencil.noc) dxn++;
1764     jdxn[i] = tmp;
1765   }
1766   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1767   PetscCall(PetscFree2(bufm, bufn));
1768   PetscFunctionReturn(PETSC_SUCCESS);
1769 }
1770 
1771 /*@
1772   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1773   Using structured grid indexing
1774 
1775   Not Collective
1776 
1777   Input Parameters:
1778 + mat  - the matrix
1779 . m    - number of rows being entered
1780 . idxm - grid coordinates for matrix rows being entered
1781 . n    - number of columns being entered
1782 . idxn - grid coordinates for matrix columns being entered
1783 . v    - a logically two-dimensional array of values
1784 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1785 
1786   Level: beginner
1787 
1788   Notes:
1789   By default the values, `v`, are row-oriented and unsorted.
1790   See `MatSetOption()` for other options.
1791 
1792   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1793   options cannot be mixed without intervening calls to the assembly
1794   routines.
1795 
1796   The grid coordinates are across the entire grid, not just the local portion
1797 
1798   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1799   as well as in C.
1800 
1801   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1802 
1803   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1804   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1805 
1806   The columns and rows in the stencil passed in MUST be contained within the
1807   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1808   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1809   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1810   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1811 
1812   Negative indices may be passed in idxm and idxn, these rows and columns are
1813   simply ignored. This allows easily inserting element stiffness matrices
1814   with homogeneous Dirichlet boundary conditions that you don't want represented
1815   in the matrix.
1816 
1817   Inspired by the structured grid interface to the HYPRE package
1818   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1819 
1820   Fortran Notes:
1821   `idxm` and `idxn` should be declared as
1822 $     MatStencil idxm(4,m),idxn(4,n)
1823   and the values inserted using
1824 .vb
1825     idxm(MatStencil_i,1) = i
1826     idxm(MatStencil_j,1) = j
1827     idxm(MatStencil_k,1) = k
1828    etc
1829 .ve
1830 
1831 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1832           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1833           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1834 @*/
1835 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1836 {
1837   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1838   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1839   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1840 
1841   PetscFunctionBegin;
1842   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1844   PetscValidType(mat, 1);
1845   PetscAssertPointer(idxm, 3);
1846   PetscAssertPointer(idxn, 5);
1847   PetscAssertPointer(v, 6);
1848 
1849   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1850     jdxm = buf;
1851     jdxn = buf + m;
1852   } else {
1853     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1854     jdxm = bufm;
1855     jdxn = bufn;
1856   }
1857   for (i = 0; i < m; i++) {
1858     for (j = 0; j < 3 - sdim; j++) dxm++;
1859     tmp = *dxm++ - starts[0];
1860     for (j = 0; j < sdim - 1; j++) {
1861       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1862       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1863     }
1864     dxm++;
1865     jdxm[i] = tmp;
1866   }
1867   for (i = 0; i < n; i++) {
1868     for (j = 0; j < 3 - sdim; j++) dxn++;
1869     tmp = *dxn++ - starts[0];
1870     for (j = 0; j < sdim - 1; j++) {
1871       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1872       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1873     }
1874     dxn++;
1875     jdxn[i] = tmp;
1876   }
1877   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1878   PetscCall(PetscFree2(bufm, bufn));
1879   PetscFunctionReturn(PETSC_SUCCESS);
1880 }
1881 
1882 /*@
1883   MatSetStencil - Sets the grid information for setting values into a matrix via
1884   `MatSetValuesStencil()`
1885 
1886   Not Collective
1887 
1888   Input Parameters:
1889 + mat    - the matrix
1890 . dim    - dimension of the grid 1, 2, or 3
1891 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1892 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1893 - dof    - number of degrees of freedom per node
1894 
1895   Level: beginner
1896 
1897   Notes:
1898   Inspired by the structured grid interface to the HYPRE package
1899   (www.llnl.gov/CASC/hyper)
1900 
1901   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1902   user.
1903 
1904 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1905           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1906 @*/
1907 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1908 {
1909   PetscFunctionBegin;
1910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1911   PetscAssertPointer(dims, 3);
1912   PetscAssertPointer(starts, 4);
1913 
1914   mat->stencil.dim = dim + (dof > 1);
1915   for (PetscInt i = 0; i < dim; i++) {
1916     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1917     mat->stencil.starts[i] = starts[dim - i - 1];
1918   }
1919   mat->stencil.dims[dim]   = dof;
1920   mat->stencil.starts[dim] = 0;
1921   mat->stencil.noc         = (PetscBool)(dof == 1);
1922   PetscFunctionReturn(PETSC_SUCCESS);
1923 }
1924 
1925 /*@C
1926   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1927 
1928   Not Collective
1929 
1930   Input Parameters:
1931 + mat  - the matrix
1932 . v    - a logically two-dimensional array of values
1933 . m    - the number of block rows
1934 . idxm - the global block indices
1935 . n    - the number of block columns
1936 . idxn - the global block indices
1937 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1938 
1939   Level: intermediate
1940 
1941   Notes:
1942   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1943   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1944 
1945   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1946   NOT the total number of rows/columns; for example, if the block size is 2 and
1947   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1948   The values in idxm would be 1 2; that is the first index for each block divided by
1949   the block size.
1950 
1951   You must call `MatSetBlockSize()` when constructing this matrix (before
1952   preallocating it).
1953 
1954   By default the values, `v`, are row-oriented, so the layout of
1955   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1956 
1957   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1958   options cannot be mixed without intervening calls to the assembly
1959   routines.
1960 
1961   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1962   as well as in C.
1963 
1964   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1965   simply ignored. This allows easily inserting element stiffness matrices
1966   with homogeneous Dirichlet boundary conditions that you don't want represented
1967   in the matrix.
1968 
1969   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1970   internal searching must be done to determine where to place the
1971   data in the matrix storage space.  By instead inserting blocks of
1972   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1973   reduced.
1974 
1975   Example:
1976 .vb
1977    Suppose m=n=2 and block size(bs) = 2 The array is
1978 
1979    1  2  | 3  4
1980    5  6  | 7  8
1981    - - - | - - -
1982    9  10 | 11 12
1983    13 14 | 15 16
1984 
1985    v[] should be passed in like
1986    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1987 
1988   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1989    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1990 .ve
1991 
1992 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1993 @*/
1994 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1995 {
1996   PetscFunctionBeginHot;
1997   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1998   PetscValidType(mat, 1);
1999   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2000   PetscAssertPointer(idxm, 3);
2001   PetscAssertPointer(idxn, 5);
2002   MatCheckPreallocated(mat, 1);
2003   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2004   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2005   if (PetscDefined(USE_DEBUG)) {
2006     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2007     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2008   }
2009   if (PetscDefined(USE_DEBUG)) {
2010     PetscInt rbs, cbs, M, N, i;
2011     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2012     PetscCall(MatGetSize(mat, &M, &N));
2013     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);
2014     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);
2015   }
2016   if (mat->assembled) {
2017     mat->was_assembled = PETSC_TRUE;
2018     mat->assembled     = PETSC_FALSE;
2019   }
2020   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2021   if (mat->ops->setvaluesblocked) {
2022     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2023   } else {
2024     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2025     PetscInt i, j, bs, cbs;
2026 
2027     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2028     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2029       iidxm = buf;
2030       iidxn = buf + m * bs;
2031     } else {
2032       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2033       iidxm = bufr;
2034       iidxn = bufc;
2035     }
2036     for (i = 0; i < m; i++) {
2037       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2038     }
2039     if (m != n || bs != cbs || idxm != idxn) {
2040       for (i = 0; i < n; i++) {
2041         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2042       }
2043     } else iidxn = iidxm;
2044     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2045     PetscCall(PetscFree2(bufr, bufc));
2046   }
2047   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2048   PetscFunctionReturn(PETSC_SUCCESS);
2049 }
2050 
2051 /*@C
2052   MatGetValues - Gets a block of local values from a matrix.
2053 
2054   Not Collective; can only return values that are owned by the give process
2055 
2056   Input Parameters:
2057 + mat  - the matrix
2058 . v    - a logically two-dimensional array for storing the values
2059 . m    - the number of rows
2060 . idxm - the  global indices of the rows
2061 . n    - the number of columns
2062 - idxn - the global indices of the columns
2063 
2064   Level: advanced
2065 
2066   Notes:
2067   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2068   The values, `v`, are then returned in a row-oriented format,
2069   analogous to that used by default in `MatSetValues()`.
2070 
2071   `MatGetValues()` uses 0-based row and column numbers in
2072   Fortran as well as in C.
2073 
2074   `MatGetValues()` requires that the matrix has been assembled
2075   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2076   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2077   without intermediate matrix assembly.
2078 
2079   Negative row or column indices will be ignored and those locations in `v` will be
2080   left unchanged.
2081 
2082   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2083   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2084   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2085 
2086 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2087 @*/
2088 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2089 {
2090   PetscFunctionBegin;
2091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2092   PetscValidType(mat, 1);
2093   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2094   PetscAssertPointer(idxm, 3);
2095   PetscAssertPointer(idxn, 5);
2096   PetscAssertPointer(v, 6);
2097   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2098   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2099   MatCheckPreallocated(mat, 1);
2100 
2101   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2102   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2103   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2104   PetscFunctionReturn(PETSC_SUCCESS);
2105 }
2106 
2107 /*@C
2108   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2109   defined previously by `MatSetLocalToGlobalMapping()`
2110 
2111   Not Collective
2112 
2113   Input Parameters:
2114 + mat  - the matrix
2115 . nrow - number of rows
2116 . irow - the row local indices
2117 . ncol - number of columns
2118 - icol - the column local indices
2119 
2120   Output Parameter:
2121 . y - a logically two-dimensional array of values
2122 
2123   Level: advanced
2124 
2125   Notes:
2126   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2127 
2128   This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2129   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2130   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2131   with `MatSetLocalToGlobalMapping()`.
2132 
2133   Developer Notes:
2134   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2135   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2136 
2137 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2138           `MatSetValuesLocal()`, `MatGetValues()`
2139 @*/
2140 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2141 {
2142   PetscFunctionBeginHot;
2143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2144   PetscValidType(mat, 1);
2145   MatCheckPreallocated(mat, 1);
2146   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2147   PetscAssertPointer(irow, 3);
2148   PetscAssertPointer(icol, 5);
2149   if (PetscDefined(USE_DEBUG)) {
2150     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2151     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2152   }
2153   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2154   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2155   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2156   else {
2157     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2158     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2159       irowm = buf;
2160       icolm = buf + nrow;
2161     } else {
2162       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2163       irowm = bufr;
2164       icolm = bufc;
2165     }
2166     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2167     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2168     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2169     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2170     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2171     PetscCall(PetscFree2(bufr, bufc));
2172   }
2173   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2174   PetscFunctionReturn(PETSC_SUCCESS);
2175 }
2176 
2177 /*@
2178   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2179   the same size. Currently, this can only be called once and creates the given matrix.
2180 
2181   Not Collective
2182 
2183   Input Parameters:
2184 + mat  - the matrix
2185 . nb   - the number of blocks
2186 . bs   - the number of rows (and columns) in each block
2187 . rows - a concatenation of the rows for each block
2188 - v    - a concatenation of logically two-dimensional arrays of values
2189 
2190   Level: advanced
2191 
2192   Note:
2193   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2194 
2195   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2196 
2197 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2198           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2199 @*/
2200 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2201 {
2202   PetscFunctionBegin;
2203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2204   PetscValidType(mat, 1);
2205   PetscAssertPointer(rows, 4);
2206   PetscAssertPointer(v, 5);
2207   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2208 
2209   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2210   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2211   else {
2212     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2213   }
2214   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2215   PetscFunctionReturn(PETSC_SUCCESS);
2216 }
2217 
2218 /*@
2219   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2220   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2221   using a local (per-processor) numbering.
2222 
2223   Not Collective
2224 
2225   Input Parameters:
2226 + x        - the matrix
2227 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2228 - cmapping - column mapping
2229 
2230   Level: intermediate
2231 
2232   Note:
2233   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2234 
2235 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2236 @*/
2237 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2238 {
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2241   PetscValidType(x, 1);
2242   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2243   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2244   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2245   else {
2246     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2247     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2248   }
2249   PetscFunctionReturn(PETSC_SUCCESS);
2250 }
2251 
2252 /*@
2253   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2254 
2255   Not Collective
2256 
2257   Input Parameter:
2258 . A - the matrix
2259 
2260   Output Parameters:
2261 + rmapping - row mapping
2262 - cmapping - column mapping
2263 
2264   Level: advanced
2265 
2266 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2267 @*/
2268 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2269 {
2270   PetscFunctionBegin;
2271   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2272   PetscValidType(A, 1);
2273   if (rmapping) {
2274     PetscAssertPointer(rmapping, 2);
2275     *rmapping = A->rmap->mapping;
2276   }
2277   if (cmapping) {
2278     PetscAssertPointer(cmapping, 3);
2279     *cmapping = A->cmap->mapping;
2280   }
2281   PetscFunctionReturn(PETSC_SUCCESS);
2282 }
2283 
2284 /*@
2285   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2286 
2287   Logically Collective
2288 
2289   Input Parameters:
2290 + A    - the matrix
2291 . rmap - row layout
2292 - cmap - column layout
2293 
2294   Level: advanced
2295 
2296   Note:
2297   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2298 
2299 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2300 @*/
2301 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2302 {
2303   PetscFunctionBegin;
2304   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2305   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2306   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2307   PetscFunctionReturn(PETSC_SUCCESS);
2308 }
2309 
2310 /*@
2311   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2312 
2313   Not Collective
2314 
2315   Input Parameter:
2316 . A - the matrix
2317 
2318   Output Parameters:
2319 + rmap - row layout
2320 - cmap - column layout
2321 
2322   Level: advanced
2323 
2324 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2325 @*/
2326 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2327 {
2328   PetscFunctionBegin;
2329   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2330   PetscValidType(A, 1);
2331   if (rmap) {
2332     PetscAssertPointer(rmap, 2);
2333     *rmap = A->rmap;
2334   }
2335   if (cmap) {
2336     PetscAssertPointer(cmap, 3);
2337     *cmap = A->cmap;
2338   }
2339   PetscFunctionReturn(PETSC_SUCCESS);
2340 }
2341 
2342 /*@C
2343   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2344   using a local numbering of the nodes.
2345 
2346   Not Collective
2347 
2348   Input Parameters:
2349 + mat  - the matrix
2350 . nrow - number of rows
2351 . irow - the row local indices
2352 . ncol - number of columns
2353 . icol - the column local indices
2354 . y    - a logically two-dimensional array of values
2355 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2356 
2357   Level: intermediate
2358 
2359   Notes:
2360   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2361   `MatSetUp()` before using this routine
2362 
2363   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2364 
2365   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2366   options cannot be mixed without intervening calls to the assembly
2367   routines.
2368 
2369   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2370   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2371 
2372   Developer Notes:
2373   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2374   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2375 
2376 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2377           `MatGetValuesLocal()`
2378 @*/
2379 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2380 {
2381   PetscFunctionBeginHot;
2382   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2383   PetscValidType(mat, 1);
2384   MatCheckPreallocated(mat, 1);
2385   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2386   PetscAssertPointer(irow, 3);
2387   PetscAssertPointer(icol, 5);
2388   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2389   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2390   if (PetscDefined(USE_DEBUG)) {
2391     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2392     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2393   }
2394 
2395   if (mat->assembled) {
2396     mat->was_assembled = PETSC_TRUE;
2397     mat->assembled     = PETSC_FALSE;
2398   }
2399   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2400   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2401   else {
2402     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2403     const PetscInt *irowm, *icolm;
2404 
2405     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2406       bufr  = buf;
2407       bufc  = buf + nrow;
2408       irowm = bufr;
2409       icolm = bufc;
2410     } else {
2411       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2412       irowm = bufr;
2413       icolm = bufc;
2414     }
2415     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2416     else irowm = irow;
2417     if (mat->cmap->mapping) {
2418       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2419         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2420       } else icolm = irowm;
2421     } else icolm = icol;
2422     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2423     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2424   }
2425   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2426   PetscFunctionReturn(PETSC_SUCCESS);
2427 }
2428 
2429 /*@C
2430   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2431   using a local ordering of the nodes a block at a time.
2432 
2433   Not Collective
2434 
2435   Input Parameters:
2436 + mat  - the matrix
2437 . nrow - number of rows
2438 . irow - the row local indices
2439 . ncol - number of columns
2440 . icol - the column local indices
2441 . y    - a logically two-dimensional array of values
2442 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2443 
2444   Level: intermediate
2445 
2446   Notes:
2447   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2448   `MatSetUp()` before using this routine
2449 
2450   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2451   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2452 
2453   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2454   options cannot be mixed without intervening calls to the assembly
2455   routines.
2456 
2457   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2458   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2459 
2460   Developer Notes:
2461   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2462   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2463 
2464 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2465           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2466 @*/
2467 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2468 {
2469   PetscFunctionBeginHot;
2470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2471   PetscValidType(mat, 1);
2472   MatCheckPreallocated(mat, 1);
2473   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2474   PetscAssertPointer(irow, 3);
2475   PetscAssertPointer(icol, 5);
2476   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2477   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2478   if (PetscDefined(USE_DEBUG)) {
2479     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2480     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);
2481   }
2482 
2483   if (mat->assembled) {
2484     mat->was_assembled = PETSC_TRUE;
2485     mat->assembled     = PETSC_FALSE;
2486   }
2487   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2488     PetscInt irbs, rbs;
2489     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2490     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2491     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2492   }
2493   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2494     PetscInt icbs, cbs;
2495     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2496     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2497     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2498   }
2499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2500   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2501   else {
2502     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2503     const PetscInt *irowm, *icolm;
2504 
2505     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2506       bufr  = buf;
2507       bufc  = buf + nrow;
2508       irowm = bufr;
2509       icolm = bufc;
2510     } else {
2511       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2512       irowm = bufr;
2513       icolm = bufc;
2514     }
2515     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2516     else irowm = irow;
2517     if (mat->cmap->mapping) {
2518       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2519         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2520       } else icolm = irowm;
2521     } else icolm = icol;
2522     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2523     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2524   }
2525   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2526   PetscFunctionReturn(PETSC_SUCCESS);
2527 }
2528 
2529 /*@
2530   MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2531 
2532   Collective
2533 
2534   Input Parameters:
2535 + mat - the matrix
2536 - x   - the vector to be multiplied
2537 
2538   Output Parameter:
2539 . y - the result
2540 
2541   Level: developer
2542 
2543   Note:
2544   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2545   call `MatMultDiagonalBlock`(A,y,y).
2546 
2547 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2548 @*/
2549 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2550 {
2551   PetscFunctionBegin;
2552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2553   PetscValidType(mat, 1);
2554   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2555   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2556 
2557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2558   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2559   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2560   MatCheckPreallocated(mat, 1);
2561 
2562   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2563   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2564   PetscFunctionReturn(PETSC_SUCCESS);
2565 }
2566 
2567 /*@
2568   MatMult - Computes the matrix-vector product, y = Ax.
2569 
2570   Neighbor-wise Collective
2571 
2572   Input Parameters:
2573 + mat - the matrix
2574 - x   - the vector to be multiplied
2575 
2576   Output Parameter:
2577 . y - the result
2578 
2579   Level: beginner
2580 
2581   Note:
2582   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2583   call `MatMult`(A,y,y).
2584 
2585 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2586 @*/
2587 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2588 {
2589   PetscFunctionBegin;
2590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2591   PetscValidType(mat, 1);
2592   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2593   VecCheckAssembled(x);
2594   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2597   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2598   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);
2599   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);
2600   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);
2601   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);
2602   PetscCall(VecSetErrorIfLocked(y, 3));
2603   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2604   MatCheckPreallocated(mat, 1);
2605 
2606   PetscCall(VecLockReadPush(x));
2607   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2608   PetscUseTypeMethod(mat, mult, x, y);
2609   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2610   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2611   PetscCall(VecLockReadPop(x));
2612   PetscFunctionReturn(PETSC_SUCCESS);
2613 }
2614 
2615 /*@
2616   MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2617 
2618   Neighbor-wise Collective
2619 
2620   Input Parameters:
2621 + mat - the matrix
2622 - x   - the vector to be multiplied
2623 
2624   Output Parameter:
2625 . y - the result
2626 
2627   Level: beginner
2628 
2629   Notes:
2630   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2631   call `MatMultTranspose`(A,y,y).
2632 
2633   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2634   use `MatMultHermitianTranspose()`
2635 
2636 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2637 @*/
2638 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2639 {
2640   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2641 
2642   PetscFunctionBegin;
2643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2644   PetscValidType(mat, 1);
2645   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2646   VecCheckAssembled(x);
2647   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2648 
2649   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2650   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2651   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2652   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2653   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2654   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2655   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2656   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2657   MatCheckPreallocated(mat, 1);
2658 
2659   if (!mat->ops->multtranspose) {
2660     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2661     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);
2662   } else op = mat->ops->multtranspose;
2663   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2664   PetscCall(VecLockReadPush(x));
2665   PetscCall((*op)(mat, x, y));
2666   PetscCall(VecLockReadPop(x));
2667   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2668   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2669   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2670   PetscFunctionReturn(PETSC_SUCCESS);
2671 }
2672 
2673 /*@
2674   MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2675 
2676   Neighbor-wise Collective
2677 
2678   Input Parameters:
2679 + mat - the matrix
2680 - x   - the vector to be multiplied
2681 
2682   Output Parameter:
2683 . y - the result
2684 
2685   Level: beginner
2686 
2687   Notes:
2688   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2689   call `MatMultHermitianTranspose`(A,y,y).
2690 
2691   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2692 
2693   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2694 
2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2696 @*/
2697 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2698 {
2699   PetscFunctionBegin;
2700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2701   PetscValidType(mat, 1);
2702   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2703   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2704 
2705   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2706   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2707   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2708   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);
2709   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);
2710   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);
2711   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);
2712   MatCheckPreallocated(mat, 1);
2713 
2714   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2715 #if defined(PETSC_USE_COMPLEX)
2716   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2717     PetscCall(VecLockReadPush(x));
2718     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2719     else PetscUseTypeMethod(mat, mult, x, y);
2720     PetscCall(VecLockReadPop(x));
2721   } else {
2722     Vec w;
2723     PetscCall(VecDuplicate(x, &w));
2724     PetscCall(VecCopy(x, w));
2725     PetscCall(VecConjugate(w));
2726     PetscCall(MatMultTranspose(mat, w, y));
2727     PetscCall(VecDestroy(&w));
2728     PetscCall(VecConjugate(y));
2729   }
2730   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2731 #else
2732   PetscCall(MatMultTranspose(mat, x, y));
2733 #endif
2734   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2735   PetscFunctionReturn(PETSC_SUCCESS);
2736 }
2737 
2738 /*@
2739   MatMultAdd -  Computes v3 = v2 + A * v1.
2740 
2741   Neighbor-wise Collective
2742 
2743   Input Parameters:
2744 + mat - the matrix
2745 . v1  - the vector to be multiplied by `mat`
2746 - v2  - the vector to be added to the result
2747 
2748   Output Parameter:
2749 . v3 - the result
2750 
2751   Level: beginner
2752 
2753   Note:
2754   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2755   call `MatMultAdd`(A,v1,v2,v1).
2756 
2757 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2758 @*/
2759 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2760 {
2761   PetscFunctionBegin;
2762   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2763   PetscValidType(mat, 1);
2764   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2765   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2766   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2767 
2768   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2769   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2770   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);
2771   /* 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);
2772      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); */
2773   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);
2774   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);
2775   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2776   MatCheckPreallocated(mat, 1);
2777 
2778   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2779   PetscCall(VecLockReadPush(v1));
2780   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2781   PetscCall(VecLockReadPop(v1));
2782   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2783   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2784   PetscFunctionReturn(PETSC_SUCCESS);
2785 }
2786 
2787 /*@
2788   MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2789 
2790   Neighbor-wise Collective
2791 
2792   Input Parameters:
2793 + mat - the matrix
2794 . v1  - the vector to be multiplied by the transpose of the matrix
2795 - v2  - the vector to be added to the result
2796 
2797   Output Parameter:
2798 . v3 - the result
2799 
2800   Level: beginner
2801 
2802   Note:
2803   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2804   call `MatMultTransposeAdd`(A,v1,v2,v1).
2805 
2806 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2807 @*/
2808 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2809 {
2810   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2811 
2812   PetscFunctionBegin;
2813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2814   PetscValidType(mat, 1);
2815   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2816   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2817   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2818 
2819   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2820   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2821   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);
2822   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);
2823   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);
2824   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2825   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2826   MatCheckPreallocated(mat, 1);
2827 
2828   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2829   PetscCall(VecLockReadPush(v1));
2830   PetscCall((*op)(mat, v1, v2, v3));
2831   PetscCall(VecLockReadPop(v1));
2832   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2833   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2834   PetscFunctionReturn(PETSC_SUCCESS);
2835 }
2836 
2837 /*@
2838   MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2839 
2840   Neighbor-wise Collective
2841 
2842   Input Parameters:
2843 + mat - the matrix
2844 . v1  - the vector to be multiplied by the Hermitian transpose
2845 - v2  - the vector to be added to the result
2846 
2847   Output Parameter:
2848 . v3 - the result
2849 
2850   Level: beginner
2851 
2852   Note:
2853   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2854   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2855 
2856 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2857 @*/
2858 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2859 {
2860   PetscFunctionBegin;
2861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2862   PetscValidType(mat, 1);
2863   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2864   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2865   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2866 
2867   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2868   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2869   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2870   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);
2871   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);
2872   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);
2873   MatCheckPreallocated(mat, 1);
2874 
2875   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2876   PetscCall(VecLockReadPush(v1));
2877   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2878   else {
2879     Vec w, z;
2880     PetscCall(VecDuplicate(v1, &w));
2881     PetscCall(VecCopy(v1, w));
2882     PetscCall(VecConjugate(w));
2883     PetscCall(VecDuplicate(v3, &z));
2884     PetscCall(MatMultTranspose(mat, w, z));
2885     PetscCall(VecDestroy(&w));
2886     PetscCall(VecConjugate(z));
2887     if (v2 != v3) {
2888       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2889     } else {
2890       PetscCall(VecAXPY(v3, 1.0, z));
2891     }
2892     PetscCall(VecDestroy(&z));
2893   }
2894   PetscCall(VecLockReadPop(v1));
2895   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2896   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2897   PetscFunctionReturn(PETSC_SUCCESS);
2898 }
2899 
2900 /*@C
2901   MatGetFactorType - gets the type of factorization it is
2902 
2903   Not Collective
2904 
2905   Input Parameter:
2906 . mat - the matrix
2907 
2908   Output Parameter:
2909 . 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`
2910 
2911   Level: intermediate
2912 
2913 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2914           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2915 @*/
2916 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2917 {
2918   PetscFunctionBegin;
2919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2920   PetscValidType(mat, 1);
2921   PetscAssertPointer(t, 2);
2922   *t = mat->factortype;
2923   PetscFunctionReturn(PETSC_SUCCESS);
2924 }
2925 
2926 /*@C
2927   MatSetFactorType - sets the type of factorization it is
2928 
2929   Logically Collective
2930 
2931   Input Parameters:
2932 + mat - the matrix
2933 - 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`
2934 
2935   Level: intermediate
2936 
2937 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2938           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2939 @*/
2940 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2941 {
2942   PetscFunctionBegin;
2943   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2944   PetscValidType(mat, 1);
2945   mat->factortype = t;
2946   PetscFunctionReturn(PETSC_SUCCESS);
2947 }
2948 
2949 /*@C
2950   MatGetInfo - Returns information about matrix storage (number of
2951   nonzeros, memory, etc.).
2952 
2953   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2954 
2955   Input Parameters:
2956 + mat  - the matrix
2957 - 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)
2958 
2959   Output Parameter:
2960 . info - matrix information context
2961 
2962   Options Database Key:
2963 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2964 
2965   Notes:
2966   The `MatInfo` context contains a variety of matrix data, including
2967   number of nonzeros allocated and used, number of mallocs during
2968   matrix assembly, etc.  Additional information for factored matrices
2969   is provided (such as the fill ratio, number of mallocs during
2970   factorization, etc.).
2971 
2972   Example:
2973   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2974   data within the MatInfo context.  For example,
2975 .vb
2976       MatInfo info;
2977       Mat     A;
2978       double  mal, nz_a, nz_u;
2979 
2980       MatGetInfo(A, MAT_LOCAL, &info);
2981       mal  = info.mallocs;
2982       nz_a = info.nz_allocated;
2983 .ve
2984 
2985   Fortran users should declare info as a double precision
2986   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2987   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2988   a complete list of parameter names.
2989 .vb
2990       double  precision info(MAT_INFO_SIZE)
2991       double  precision mal, nz_a
2992       Mat     A
2993       integer ierr
2994 
2995       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2996       mal = info(MAT_INFO_MALLOCS)
2997       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2998 .ve
2999 
3000   Level: intermediate
3001 
3002   Developer Notes:
3003   The Fortran interface is not autogenerated as the
3004   interface definition cannot be generated correctly [due to `MatInfo` argument]
3005 
3006 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3007 @*/
3008 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3009 {
3010   PetscFunctionBegin;
3011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3012   PetscValidType(mat, 1);
3013   PetscAssertPointer(info, 3);
3014   MatCheckPreallocated(mat, 1);
3015   PetscUseTypeMethod(mat, getinfo, flag, info);
3016   PetscFunctionReturn(PETSC_SUCCESS);
3017 }
3018 
3019 /*
3020    This is used by external packages where it is not easy to get the info from the actual
3021    matrix factorization.
3022 */
3023 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3024 {
3025   PetscFunctionBegin;
3026   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3027   PetscFunctionReturn(PETSC_SUCCESS);
3028 }
3029 
3030 /*@C
3031   MatLUFactor - Performs in-place LU factorization of matrix.
3032 
3033   Collective
3034 
3035   Input Parameters:
3036 + mat  - the matrix
3037 . row  - row permutation
3038 . col  - column permutation
3039 - info - options for factorization, includes
3040 .vb
3041           fill - expected fill as ratio of original fill.
3042           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3043                    Run with the option -info to determine an optimal value to use
3044 .ve
3045 
3046   Level: developer
3047 
3048   Notes:
3049   Most users should employ the `KSP` interface for linear solvers
3050   instead of working directly with matrix algebra routines such as this.
3051   See, e.g., `KSPCreate()`.
3052 
3053   This changes the state of the matrix to a factored matrix; it cannot be used
3054   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3055 
3056   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3057   when not using `KSP`.
3058 
3059   Developer Notes:
3060   The Fortran interface is not autogenerated as the
3061   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3062 
3063 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3064           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3065 @*/
3066 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3067 {
3068   MatFactorInfo tinfo;
3069 
3070   PetscFunctionBegin;
3071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3072   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3073   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3074   if (info) PetscAssertPointer(info, 4);
3075   PetscValidType(mat, 1);
3076   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3077   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3078   MatCheckPreallocated(mat, 1);
3079   if (!info) {
3080     PetscCall(MatFactorInfoInitialize(&tinfo));
3081     info = &tinfo;
3082   }
3083 
3084   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3085   PetscUseTypeMethod(mat, lufactor, row, col, info);
3086   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3087   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3088   PetscFunctionReturn(PETSC_SUCCESS);
3089 }
3090 
3091 /*@C
3092   MatILUFactor - Performs in-place ILU factorization of matrix.
3093 
3094   Collective
3095 
3096   Input Parameters:
3097 + mat  - the matrix
3098 . row  - row permutation
3099 . col  - column permutation
3100 - info - structure containing
3101 .vb
3102       levels - number of levels of fill.
3103       expected fill - as ratio of original fill.
3104       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3105                 missing diagonal entries)
3106 .ve
3107 
3108   Level: developer
3109 
3110   Notes:
3111   Most users should employ the `KSP` interface for linear solvers
3112   instead of working directly with matrix algebra routines such as this.
3113   See, e.g., `KSPCreate()`.
3114 
3115   Probably really in-place only when level of fill is zero, otherwise allocates
3116   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3117   when not using `KSP`.
3118 
3119   Developer Notes:
3120   The Fortran interface is not autogenerated as the
3121   interface definition cannot be generated correctly [due to MatFactorInfo]
3122 
3123 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3124 @*/
3125 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3126 {
3127   PetscFunctionBegin;
3128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3129   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3130   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3131   PetscAssertPointer(info, 4);
3132   PetscValidType(mat, 1);
3133   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3134   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3135   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3136   MatCheckPreallocated(mat, 1);
3137 
3138   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3139   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3140   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3141   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3142   PetscFunctionReturn(PETSC_SUCCESS);
3143 }
3144 
3145 /*@C
3146   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3147   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3148 
3149   Collective
3150 
3151   Input Parameters:
3152 + fact - the factor matrix obtained with `MatGetFactor()`
3153 . mat  - the matrix
3154 . row  - the row permutation
3155 . col  - the column permutation
3156 - info - options for factorization, includes
3157 .vb
3158           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3159           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3160 .ve
3161 
3162   Level: developer
3163 
3164   Notes:
3165   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3166 
3167   Most users should employ the simplified `KSP` interface for linear solvers
3168   instead of working directly with matrix algebra routines such as this.
3169   See, e.g., `KSPCreate()`.
3170 
3171   Developer Notes:
3172   The Fortran interface is not autogenerated as the
3173   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3174 
3175 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3176 @*/
3177 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3178 {
3179   MatFactorInfo tinfo;
3180 
3181   PetscFunctionBegin;
3182   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3184   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3185   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3186   if (info) PetscAssertPointer(info, 5);
3187   PetscValidType(fact, 1);
3188   PetscValidType(mat, 2);
3189   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3190   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3191   MatCheckPreallocated(mat, 2);
3192   if (!info) {
3193     PetscCall(MatFactorInfoInitialize(&tinfo));
3194     info = &tinfo;
3195   }
3196 
3197   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3198   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3199   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3200   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3201   PetscFunctionReturn(PETSC_SUCCESS);
3202 }
3203 
3204 /*@C
3205   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3206   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3207 
3208   Collective
3209 
3210   Input Parameters:
3211 + fact - the factor matrix obtained with `MatGetFactor()`
3212 . mat  - the matrix
3213 - info - options for factorization
3214 
3215   Level: developer
3216 
3217   Notes:
3218   See `MatLUFactor()` for in-place factorization.  See
3219   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3220 
3221   Most users should employ the `KSP` interface for linear solvers
3222   instead of working directly with matrix algebra routines such as this.
3223   See, e.g., `KSPCreate()`.
3224 
3225   Developer Notes:
3226   The Fortran interface is not autogenerated as the
3227   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3228 
3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3230 @*/
3231 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3232 {
3233   MatFactorInfo tinfo;
3234 
3235   PetscFunctionBegin;
3236   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3238   PetscValidType(fact, 1);
3239   PetscValidType(mat, 2);
3240   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3241   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,
3242              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3243 
3244   MatCheckPreallocated(mat, 2);
3245   if (!info) {
3246     PetscCall(MatFactorInfoInitialize(&tinfo));
3247     info = &tinfo;
3248   }
3249 
3250   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3251   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3252   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3253   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3254   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3255   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3256   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3257   PetscFunctionReturn(PETSC_SUCCESS);
3258 }
3259 
3260 /*@C
3261   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3262   symmetric matrix.
3263 
3264   Collective
3265 
3266   Input Parameters:
3267 + mat  - the matrix
3268 . perm - row and column permutations
3269 - info - expected fill as ratio of original fill
3270 
3271   Level: developer
3272 
3273   Notes:
3274   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3275   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3276 
3277   Most users should employ the `KSP` interface for linear solvers
3278   instead of working directly with matrix algebra routines such as this.
3279   See, e.g., `KSPCreate()`.
3280 
3281   Developer Notes:
3282   The Fortran interface is not autogenerated as the
3283   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3284 
3285 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3286           `MatGetOrdering()`
3287 @*/
3288 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3289 {
3290   MatFactorInfo tinfo;
3291 
3292   PetscFunctionBegin;
3293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3294   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3295   if (info) PetscAssertPointer(info, 3);
3296   PetscValidType(mat, 1);
3297   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3298   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3299   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3300   MatCheckPreallocated(mat, 1);
3301   if (!info) {
3302     PetscCall(MatFactorInfoInitialize(&tinfo));
3303     info = &tinfo;
3304   }
3305 
3306   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3307   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3308   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3309   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3310   PetscFunctionReturn(PETSC_SUCCESS);
3311 }
3312 
3313 /*@C
3314   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3315   of a symmetric matrix.
3316 
3317   Collective
3318 
3319   Input Parameters:
3320 + fact - the factor matrix obtained with `MatGetFactor()`
3321 . mat  - the matrix
3322 . perm - row and column permutations
3323 - info - options for factorization, includes
3324 .vb
3325           fill - expected fill as ratio of original fill.
3326           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3327                    Run with the option -info to determine an optimal value to use
3328 .ve
3329 
3330   Level: developer
3331 
3332   Notes:
3333   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3334   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3335 
3336   Most users should employ the `KSP` interface for linear solvers
3337   instead of working directly with matrix algebra routines such as this.
3338   See, e.g., `KSPCreate()`.
3339 
3340   Developer Notes:
3341   The Fortran interface is not autogenerated as the
3342   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3343 
3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3345           `MatGetOrdering()`
3346 @*/
3347 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3348 {
3349   MatFactorInfo tinfo;
3350 
3351   PetscFunctionBegin;
3352   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3353   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3354   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3355   if (info) PetscAssertPointer(info, 4);
3356   PetscValidType(fact, 1);
3357   PetscValidType(mat, 2);
3358   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3359   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3360   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3361   MatCheckPreallocated(mat, 2);
3362   if (!info) {
3363     PetscCall(MatFactorInfoInitialize(&tinfo));
3364     info = &tinfo;
3365   }
3366 
3367   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3368   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3369   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3370   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3371   PetscFunctionReturn(PETSC_SUCCESS);
3372 }
3373 
3374 /*@C
3375   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3376   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3377   `MatCholeskyFactorSymbolic()`.
3378 
3379   Collective
3380 
3381   Input Parameters:
3382 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3383 . mat  - the initial matrix that is to be factored
3384 - info - options for factorization
3385 
3386   Level: developer
3387 
3388   Note:
3389   Most users should employ the `KSP` interface for linear solvers
3390   instead of working directly with matrix algebra routines such as this.
3391   See, e.g., `KSPCreate()`.
3392 
3393   Developer Notes:
3394   The Fortran interface is not autogenerated as the
3395   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3396 
3397 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3398 @*/
3399 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3400 {
3401   MatFactorInfo tinfo;
3402 
3403   PetscFunctionBegin;
3404   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3406   PetscValidType(fact, 1);
3407   PetscValidType(mat, 2);
3408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3409   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,
3410              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3411   MatCheckPreallocated(mat, 2);
3412   if (!info) {
3413     PetscCall(MatFactorInfoInitialize(&tinfo));
3414     info = &tinfo;
3415   }
3416 
3417   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3418   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3419   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3420   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3421   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3422   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3423   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3424   PetscFunctionReturn(PETSC_SUCCESS);
3425 }
3426 
3427 /*@
3428   MatQRFactor - Performs in-place QR factorization of matrix.
3429 
3430   Collective
3431 
3432   Input Parameters:
3433 + mat  - the matrix
3434 . col  - column permutation
3435 - info - options for factorization, includes
3436 .vb
3437           fill - expected fill as ratio of original fill.
3438           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3439                    Run with the option -info to determine an optimal value to use
3440 .ve
3441 
3442   Level: developer
3443 
3444   Notes:
3445   Most users should employ the `KSP` interface for linear solvers
3446   instead of working directly with matrix algebra routines such as this.
3447   See, e.g., `KSPCreate()`.
3448 
3449   This changes the state of the matrix to a factored matrix; it cannot be used
3450   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3451 
3452   Developer Notes:
3453   The Fortran interface is not autogenerated as the
3454   interface definition cannot be generated correctly [due to MatFactorInfo]
3455 
3456 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3457           `MatSetUnfactored()`
3458 @*/
3459 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3460 {
3461   PetscFunctionBegin;
3462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3463   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3464   if (info) PetscAssertPointer(info, 3);
3465   PetscValidType(mat, 1);
3466   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3467   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3468   MatCheckPreallocated(mat, 1);
3469   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3470   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3471   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3472   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3473   PetscFunctionReturn(PETSC_SUCCESS);
3474 }
3475 
3476 /*@
3477   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3478   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3479 
3480   Collective
3481 
3482   Input Parameters:
3483 + fact - the factor matrix obtained with `MatGetFactor()`
3484 . mat  - the matrix
3485 . col  - column permutation
3486 - info - options for factorization, includes
3487 .vb
3488           fill - expected fill as ratio of original fill.
3489           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3490                    Run with the option -info to determine an optimal value to use
3491 .ve
3492 
3493   Level: developer
3494 
3495   Note:
3496   Most users should employ the `KSP` interface for linear solvers
3497   instead of working directly with matrix algebra routines such as this.
3498   See, e.g., `KSPCreate()`.
3499 
3500   Developer Notes:
3501   The Fortran interface is not autogenerated as the
3502   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3503 
3504 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3505 @*/
3506 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3507 {
3508   MatFactorInfo tinfo;
3509 
3510   PetscFunctionBegin;
3511   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3512   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3513   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3514   if (info) PetscAssertPointer(info, 4);
3515   PetscValidType(fact, 1);
3516   PetscValidType(mat, 2);
3517   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3518   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3519   MatCheckPreallocated(mat, 2);
3520   if (!info) {
3521     PetscCall(MatFactorInfoInitialize(&tinfo));
3522     info = &tinfo;
3523   }
3524 
3525   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3526   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3527   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3528   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3529   PetscFunctionReturn(PETSC_SUCCESS);
3530 }
3531 
3532 /*@
3533   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3534   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3535 
3536   Collective
3537 
3538   Input Parameters:
3539 + fact - the factor matrix obtained with `MatGetFactor()`
3540 . mat  - the matrix
3541 - info - options for factorization
3542 
3543   Level: developer
3544 
3545   Notes:
3546   See `MatQRFactor()` for in-place factorization.
3547 
3548   Most users should employ the `KSP` interface for linear solvers
3549   instead of working directly with matrix algebra routines such as this.
3550   See, e.g., `KSPCreate()`.
3551 
3552   Developer Notes:
3553   The Fortran interface is not autogenerated as the
3554   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3555 
3556 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3557 @*/
3558 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3559 {
3560   MatFactorInfo tinfo;
3561 
3562   PetscFunctionBegin;
3563   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3565   PetscValidType(fact, 1);
3566   PetscValidType(mat, 2);
3567   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3568   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,
3569              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3570 
3571   MatCheckPreallocated(mat, 2);
3572   if (!info) {
3573     PetscCall(MatFactorInfoInitialize(&tinfo));
3574     info = &tinfo;
3575   }
3576 
3577   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3578   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3579   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3580   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3581   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3582   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3583   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3584   PetscFunctionReturn(PETSC_SUCCESS);
3585 }
3586 
3587 /*@
3588   MatSolve - Solves A x = b, given a factored matrix.
3589 
3590   Neighbor-wise Collective
3591 
3592   Input Parameters:
3593 + mat - the factored matrix
3594 - b   - the right-hand-side vector
3595 
3596   Output Parameter:
3597 . x - the result vector
3598 
3599   Level: developer
3600 
3601   Notes:
3602   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3603   call `MatSolve`(A,x,x).
3604 
3605   Most users should employ the `KSP` interface for linear solvers
3606   instead of working directly with matrix algebra routines such as this.
3607   See, e.g., `KSPCreate()`.
3608 
3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3610 @*/
3611 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3612 {
3613   PetscFunctionBegin;
3614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3615   PetscValidType(mat, 1);
3616   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3617   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3618   PetscCheckSameComm(mat, 1, b, 2);
3619   PetscCheckSameComm(mat, 1, x, 3);
3620   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3621   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);
3622   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);
3623   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);
3624   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3625   MatCheckPreallocated(mat, 1);
3626 
3627   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3628   if (mat->factorerrortype) {
3629     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3630     PetscCall(VecSetInf(x));
3631   } else PetscUseTypeMethod(mat, solve, b, x);
3632   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3633   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3634   PetscFunctionReturn(PETSC_SUCCESS);
3635 }
3636 
3637 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3638 {
3639   Vec      b, x;
3640   PetscInt N, i;
3641   PetscErrorCode (*f)(Mat, Vec, Vec);
3642   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3643 
3644   PetscFunctionBegin;
3645   if (A->factorerrortype) {
3646     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3647     PetscCall(MatSetInf(X));
3648     PetscFunctionReturn(PETSC_SUCCESS);
3649   }
3650   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3651   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3652   PetscCall(MatBoundToCPU(A, &Abound));
3653   if (!Abound) {
3654     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3655     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3656   }
3657 #if PetscDefined(HAVE_CUDA)
3658   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3659   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3660 #elif PetscDefined(HAVE_HIP)
3661   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3662   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3663 #endif
3664   PetscCall(MatGetSize(B, NULL, &N));
3665   for (i = 0; i < N; i++) {
3666     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3667     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3668     PetscCall((*f)(A, b, x));
3669     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3670     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3671   }
3672   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3673   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3674   PetscFunctionReturn(PETSC_SUCCESS);
3675 }
3676 
3677 /*@
3678   MatMatSolve - Solves A X = B, given a factored matrix.
3679 
3680   Neighbor-wise Collective
3681 
3682   Input Parameters:
3683 + A - the factored matrix
3684 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3685 
3686   Output Parameter:
3687 . X - the result matrix (dense matrix)
3688 
3689   Level: developer
3690 
3691   Note:
3692   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3693   otherwise, `B` and `X` cannot be the same.
3694 
3695 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3696 @*/
3697 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3698 {
3699   PetscFunctionBegin;
3700   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3701   PetscValidType(A, 1);
3702   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3703   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3704   PetscCheckSameComm(A, 1, B, 2);
3705   PetscCheckSameComm(A, 1, X, 3);
3706   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3707   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3708   PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3709   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3710   MatCheckPreallocated(A, 1);
3711 
3712   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3713   if (!A->ops->matsolve) {
3714     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3715     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3716   } else PetscUseTypeMethod(A, matsolve, B, X);
3717   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3718   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3719   PetscFunctionReturn(PETSC_SUCCESS);
3720 }
3721 
3722 /*@
3723   MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3724 
3725   Neighbor-wise Collective
3726 
3727   Input Parameters:
3728 + A - the factored matrix
3729 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3730 
3731   Output Parameter:
3732 . X - the result matrix (dense matrix)
3733 
3734   Level: developer
3735 
3736   Note:
3737   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3738   call `MatMatSolveTranspose`(A,X,X).
3739 
3740 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3741 @*/
3742 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3743 {
3744   PetscFunctionBegin;
3745   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3746   PetscValidType(A, 1);
3747   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3748   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3749   PetscCheckSameComm(A, 1, B, 2);
3750   PetscCheckSameComm(A, 1, X, 3);
3751   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3752   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);
3753   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);
3754   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);
3755   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");
3756   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3757   MatCheckPreallocated(A, 1);
3758 
3759   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3760   if (!A->ops->matsolvetranspose) {
3761     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3762     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3763   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3764   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(PETSC_SUCCESS);
3767 }
3768 
3769 /*@
3770   MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3771 
3772   Neighbor-wise Collective
3773 
3774   Input Parameters:
3775 + A  - the factored matrix
3776 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3777 
3778   Output Parameter:
3779 . X - the result matrix (dense matrix)
3780 
3781   Level: developer
3782 
3783   Note:
3784   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
3785   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3786 
3787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3788 @*/
3789 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3790 {
3791   PetscFunctionBegin;
3792   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3793   PetscValidType(A, 1);
3794   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3795   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3796   PetscCheckSameComm(A, 1, Bt, 2);
3797   PetscCheckSameComm(A, 1, X, 3);
3798 
3799   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3800   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);
3801   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);
3802   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");
3803   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3804   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3805   MatCheckPreallocated(A, 1);
3806 
3807   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3808   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3809   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3810   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3811   PetscFunctionReturn(PETSC_SUCCESS);
3812 }
3813 
3814 /*@
3815   MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3816   U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3817 
3818   Neighbor-wise Collective
3819 
3820   Input Parameters:
3821 + mat - the factored matrix
3822 - b   - the right-hand-side vector
3823 
3824   Output Parameter:
3825 . x - the result vector
3826 
3827   Level: developer
3828 
3829   Notes:
3830   `MatSolve()` should be used for most applications, as it performs
3831   a forward solve followed by a backward solve.
3832 
3833   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3834   call `MatForwardSolve`(A,x,x).
3835 
3836   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3837   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3838   `MatForwardSolve()` solves U^T*D y = b, and
3839   `MatBackwardSolve()` solves U x = y.
3840   Thus they do not provide a symmetric preconditioner.
3841 
3842 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3843 @*/
3844 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3845 {
3846   PetscFunctionBegin;
3847   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3848   PetscValidType(mat, 1);
3849   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3850   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3851   PetscCheckSameComm(mat, 1, b, 2);
3852   PetscCheckSameComm(mat, 1, x, 3);
3853   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3854   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);
3855   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);
3856   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);
3857   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3858   MatCheckPreallocated(mat, 1);
3859 
3860   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3861   PetscUseTypeMethod(mat, forwardsolve, b, x);
3862   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3863   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3864   PetscFunctionReturn(PETSC_SUCCESS);
3865 }
3866 
3867 /*@
3868   MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3869   D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3870 
3871   Neighbor-wise Collective
3872 
3873   Input Parameters:
3874 + mat - the factored matrix
3875 - b   - the right-hand-side vector
3876 
3877   Output Parameter:
3878 . x - the result vector
3879 
3880   Level: developer
3881 
3882   Notes:
3883   `MatSolve()` should be used for most applications, as it performs
3884   a forward solve followed by a backward solve.
3885 
3886   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3887   call `MatBackwardSolve`(A,x,x).
3888 
3889   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3890   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3891   `MatForwardSolve()` solves U^T*D y = b, and
3892   `MatBackwardSolve()` solves U x = y.
3893   Thus they do not provide a symmetric preconditioner.
3894 
3895 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3896 @*/
3897 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3898 {
3899   PetscFunctionBegin;
3900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3901   PetscValidType(mat, 1);
3902   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3903   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3904   PetscCheckSameComm(mat, 1, b, 2);
3905   PetscCheckSameComm(mat, 1, x, 3);
3906   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3907   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);
3908   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);
3909   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);
3910   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3911   MatCheckPreallocated(mat, 1);
3912 
3913   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3914   PetscUseTypeMethod(mat, backwardsolve, b, x);
3915   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3916   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3917   PetscFunctionReturn(PETSC_SUCCESS);
3918 }
3919 
3920 /*@
3921   MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3922 
3923   Neighbor-wise Collective
3924 
3925   Input Parameters:
3926 + mat - the factored matrix
3927 . b   - the right-hand-side vector
3928 - y   - the vector to be added to
3929 
3930   Output Parameter:
3931 . x - the result vector
3932 
3933   Level: developer
3934 
3935   Note:
3936   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3937   call `MatSolveAdd`(A,x,y,x).
3938 
3939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3940 @*/
3941 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3942 {
3943   PetscScalar one = 1.0;
3944   Vec         tmp;
3945 
3946   PetscFunctionBegin;
3947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3948   PetscValidType(mat, 1);
3949   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3950   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3951   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3952   PetscCheckSameComm(mat, 1, b, 2);
3953   PetscCheckSameComm(mat, 1, y, 3);
3954   PetscCheckSameComm(mat, 1, x, 4);
3955   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3956   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);
3957   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);
3958   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);
3959   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);
3960   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);
3961   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3962   MatCheckPreallocated(mat, 1);
3963 
3964   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3965   if (mat->factorerrortype) {
3966     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3967     PetscCall(VecSetInf(x));
3968   } else if (mat->ops->solveadd) {
3969     PetscUseTypeMethod(mat, solveadd, b, y, x);
3970   } else {
3971     /* do the solve then the add manually */
3972     if (x != y) {
3973       PetscCall(MatSolve(mat, b, x));
3974       PetscCall(VecAXPY(x, one, y));
3975     } else {
3976       PetscCall(VecDuplicate(x, &tmp));
3977       PetscCall(VecCopy(x, tmp));
3978       PetscCall(MatSolve(mat, b, x));
3979       PetscCall(VecAXPY(x, one, tmp));
3980       PetscCall(VecDestroy(&tmp));
3981     }
3982   }
3983   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3984   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3985   PetscFunctionReturn(PETSC_SUCCESS);
3986 }
3987 
3988 /*@
3989   MatSolveTranspose - Solves A' x = b, given a factored matrix.
3990 
3991   Neighbor-wise Collective
3992 
3993   Input Parameters:
3994 + mat - the factored matrix
3995 - b   - the right-hand-side vector
3996 
3997   Output Parameter:
3998 . x - the result vector
3999 
4000   Level: developer
4001 
4002   Notes:
4003   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4004   call `MatSolveTranspose`(A,x,x).
4005 
4006   Most users should employ the `KSP` interface for linear solvers
4007   instead of working directly with matrix algebra routines such as this.
4008   See, e.g., `KSPCreate()`.
4009 
4010 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4011 @*/
4012 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4013 {
4014   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4015 
4016   PetscFunctionBegin;
4017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4018   PetscValidType(mat, 1);
4019   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4020   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4021   PetscCheckSameComm(mat, 1, b, 2);
4022   PetscCheckSameComm(mat, 1, x, 3);
4023   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4024   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);
4025   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);
4026   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4027   MatCheckPreallocated(mat, 1);
4028   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4029   if (mat->factorerrortype) {
4030     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4031     PetscCall(VecSetInf(x));
4032   } else {
4033     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4034     PetscCall((*f)(mat, b, x));
4035   }
4036   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4037   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4038   PetscFunctionReturn(PETSC_SUCCESS);
4039 }
4040 
4041 /*@
4042   MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4043   factored matrix.
4044 
4045   Neighbor-wise Collective
4046 
4047   Input Parameters:
4048 + mat - the factored matrix
4049 . b   - the right-hand-side vector
4050 - y   - the vector to be added to
4051 
4052   Output Parameter:
4053 . x - the result vector
4054 
4055   Level: developer
4056 
4057   Note:
4058   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4059   call `MatSolveTransposeAdd`(A,x,y,x).
4060 
4061 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4062 @*/
4063 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4064 {
4065   PetscScalar one = 1.0;
4066   Vec         tmp;
4067   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4068 
4069   PetscFunctionBegin;
4070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4071   PetscValidType(mat, 1);
4072   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4073   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4074   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4075   PetscCheckSameComm(mat, 1, b, 2);
4076   PetscCheckSameComm(mat, 1, y, 3);
4077   PetscCheckSameComm(mat, 1, x, 4);
4078   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4079   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);
4080   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);
4081   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);
4082   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);
4083   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4084   MatCheckPreallocated(mat, 1);
4085 
4086   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4087   if (mat->factorerrortype) {
4088     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4089     PetscCall(VecSetInf(x));
4090   } else if (f) {
4091     PetscCall((*f)(mat, b, y, x));
4092   } else {
4093     /* do the solve then the add manually */
4094     if (x != y) {
4095       PetscCall(MatSolveTranspose(mat, b, x));
4096       PetscCall(VecAXPY(x, one, y));
4097     } else {
4098       PetscCall(VecDuplicate(x, &tmp));
4099       PetscCall(VecCopy(x, tmp));
4100       PetscCall(MatSolveTranspose(mat, b, x));
4101       PetscCall(VecAXPY(x, one, tmp));
4102       PetscCall(VecDestroy(&tmp));
4103     }
4104   }
4105   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4106   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4107   PetscFunctionReturn(PETSC_SUCCESS);
4108 }
4109 
4110 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4111 /*@
4112   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4113 
4114   Neighbor-wise Collective
4115 
4116   Input Parameters:
4117 + mat   - the matrix
4118 . b     - the right hand side
4119 . omega - the relaxation factor
4120 . flag  - flag indicating the type of SOR (see below)
4121 . shift - diagonal shift
4122 . its   - the number of iterations
4123 - lits  - the number of local iterations
4124 
4125   Output Parameter:
4126 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4127 
4128   SOR Flags:
4129 +     `SOR_FORWARD_SWEEP` - forward SOR
4130 .     `SOR_BACKWARD_SWEEP` - backward SOR
4131 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4132 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4133 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4134 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4135 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4136 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4137   upper/lower triangular part of matrix to
4138   vector (with omega)
4139 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4140 
4141   Level: developer
4142 
4143   Notes:
4144   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4145   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4146   on each processor.
4147 
4148   Application programmers will not generally use `MatSOR()` directly,
4149   but instead will employ the `KSP`/`PC` interface.
4150 
4151   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4152 
4153   Most users should employ the `KSP` interface for linear solvers
4154   instead of working directly with matrix algebra routines such as this.
4155   See, e.g., `KSPCreate()`.
4156 
4157   Vectors `x` and `b` CANNOT be the same
4158 
4159   The flags are implemented as bitwise inclusive or operations.
4160   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4161   to specify a zero initial guess for SSOR.
4162 
4163   Developer Notes:
4164   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4165 
4166 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4167 @*/
4168 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4169 {
4170   PetscFunctionBegin;
4171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4172   PetscValidType(mat, 1);
4173   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4174   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4175   PetscCheckSameComm(mat, 1, b, 2);
4176   PetscCheckSameComm(mat, 1, x, 8);
4177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4179   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);
4180   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);
4181   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);
4182   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4183   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4184   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4185 
4186   MatCheckPreallocated(mat, 1);
4187   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4188   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4189   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4190   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4191   PetscFunctionReturn(PETSC_SUCCESS);
4192 }
4193 
4194 /*
4195       Default matrix copy routine.
4196 */
4197 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4198 {
4199   PetscInt           i, rstart = 0, rend = 0, nz;
4200   const PetscInt    *cwork;
4201   const PetscScalar *vwork;
4202 
4203   PetscFunctionBegin;
4204   if (B->assembled) PetscCall(MatZeroEntries(B));
4205   if (str == SAME_NONZERO_PATTERN) {
4206     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4207     for (i = rstart; i < rend; i++) {
4208       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4209       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4210       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4211     }
4212   } else {
4213     PetscCall(MatAYPX(B, 0.0, A, str));
4214   }
4215   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4216   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4217   PetscFunctionReturn(PETSC_SUCCESS);
4218 }
4219 
4220 /*@
4221   MatCopy - Copies a matrix to another matrix.
4222 
4223   Collective
4224 
4225   Input Parameters:
4226 + A   - the matrix
4227 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4228 
4229   Output Parameter:
4230 . B - where the copy is put
4231 
4232   Level: intermediate
4233 
4234   Notes:
4235   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4236 
4237   `MatCopy()` copies the matrix entries of a matrix to another existing
4238   matrix (after first zeroing the second matrix).  A related routine is
4239   `MatConvert()`, which first creates a new matrix and then copies the data.
4240 
4241 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4242 @*/
4243 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4244 {
4245   PetscInt i;
4246 
4247   PetscFunctionBegin;
4248   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4249   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4250   PetscValidType(A, 1);
4251   PetscValidType(B, 2);
4252   PetscCheckSameComm(A, 1, B, 2);
4253   MatCheckPreallocated(B, 2);
4254   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4255   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4256   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,
4257              A->cmap->N, B->cmap->N);
4258   MatCheckPreallocated(A, 1);
4259   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4260 
4261   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4262   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4263   else PetscCall(MatCopy_Basic(A, B, str));
4264 
4265   B->stencil.dim = A->stencil.dim;
4266   B->stencil.noc = A->stencil.noc;
4267   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4268     B->stencil.dims[i]   = A->stencil.dims[i];
4269     B->stencil.starts[i] = A->stencil.starts[i];
4270   }
4271 
4272   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4273   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4274   PetscFunctionReturn(PETSC_SUCCESS);
4275 }
4276 
4277 /*@C
4278   MatConvert - Converts a matrix to another matrix, either of the same
4279   or different type.
4280 
4281   Collective
4282 
4283   Input Parameters:
4284 + mat     - the matrix
4285 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4286    same type as the original matrix.
4287 - reuse   - denotes if the destination matrix is to be created or reused.
4288    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
4289    `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).
4290 
4291   Output Parameter:
4292 . M - pointer to place new matrix
4293 
4294   Level: intermediate
4295 
4296   Notes:
4297   `MatConvert()` first creates a new matrix and then copies the data from
4298   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4299   entries of one matrix to another already existing matrix context.
4300 
4301   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4302   the MPI communicator of the generated matrix is always the same as the communicator
4303   of the input matrix.
4304 
4305 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4306 @*/
4307 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4308 {
4309   PetscBool  sametype, issame, flg;
4310   PetscBool3 issymmetric, ishermitian;
4311   char       convname[256], mtype[256];
4312   Mat        B;
4313 
4314   PetscFunctionBegin;
4315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4316   PetscValidType(mat, 1);
4317   PetscAssertPointer(M, 4);
4318   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4319   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4320   MatCheckPreallocated(mat, 1);
4321 
4322   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4323   if (flg) newtype = mtype;
4324 
4325   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4326   PetscCall(PetscStrcmp(newtype, "same", &issame));
4327   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4328   if (reuse == MAT_REUSE_MATRIX) {
4329     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4330     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4331   }
4332 
4333   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4334     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4335     PetscFunctionReturn(PETSC_SUCCESS);
4336   }
4337 
4338   /* Cache Mat options because some converters use MatHeaderReplace  */
4339   issymmetric = mat->symmetric;
4340   ishermitian = mat->hermitian;
4341 
4342   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4343     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4344     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4345   } else {
4346     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4347     const char *prefix[3]                                 = {"seq", "mpi", ""};
4348     PetscInt    i;
4349     /*
4350        Order of precedence:
4351        0) See if newtype is a superclass of the current matrix.
4352        1) See if a specialized converter is known to the current matrix.
4353        2) See if a specialized converter is known to the desired matrix class.
4354        3) See if a good general converter is registered for the desired class
4355           (as of 6/27/03 only MATMPIADJ falls into this category).
4356        4) See if a good general converter is known for the current matrix.
4357        5) Use a really basic converter.
4358     */
4359 
4360     /* 0) See if newtype is a superclass of the current matrix.
4361           i.e mat is mpiaij and newtype is aij */
4362     for (i = 0; i < 2; i++) {
4363       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4365       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4366       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4367       if (flg) {
4368         if (reuse == MAT_INPLACE_MATRIX) {
4369           PetscCall(PetscInfo(mat, "Early return\n"));
4370           PetscFunctionReturn(PETSC_SUCCESS);
4371         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4372           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4373           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4374           PetscFunctionReturn(PETSC_SUCCESS);
4375         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4376           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4377           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4378           PetscFunctionReturn(PETSC_SUCCESS);
4379         }
4380       }
4381     }
4382     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4383     for (i = 0; i < 3; i++) {
4384       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4385       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4386       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4387       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4388       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4390       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4391       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4392       if (conv) goto foundconv;
4393     }
4394 
4395     /* 2)  See if a specialized converter is known to the desired matrix class. */
4396     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4397     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4398     PetscCall(MatSetType(B, newtype));
4399     for (i = 0; i < 3; i++) {
4400       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4401       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4402       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4403       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4404       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4405       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4406       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4407       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4408       if (conv) {
4409         PetscCall(MatDestroy(&B));
4410         goto foundconv;
4411       }
4412     }
4413 
4414     /* 3) See if a good general converter is registered for the desired class */
4415     conv = B->ops->convertfrom;
4416     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4417     PetscCall(MatDestroy(&B));
4418     if (conv) goto foundconv;
4419 
4420     /* 4) See if a good general converter is known for the current matrix */
4421     if (mat->ops->convert) conv = mat->ops->convert;
4422     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4423     if (conv) goto foundconv;
4424 
4425     /* 5) Use a really basic converter. */
4426     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4427     conv = MatConvert_Basic;
4428 
4429   foundconv:
4430     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4431     PetscCall((*conv)(mat, newtype, reuse, M));
4432     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4433       /* the block sizes must be same if the mappings are copied over */
4434       (*M)->rmap->bs = mat->rmap->bs;
4435       (*M)->cmap->bs = mat->cmap->bs;
4436       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4437       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4438       (*M)->rmap->mapping = mat->rmap->mapping;
4439       (*M)->cmap->mapping = mat->cmap->mapping;
4440     }
4441     (*M)->stencil.dim = mat->stencil.dim;
4442     (*M)->stencil.noc = mat->stencil.noc;
4443     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4444       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4445       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4446     }
4447     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4448   }
4449   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4450 
4451   /* Copy Mat options */
4452   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4453   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4454   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4455   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4456   PetscFunctionReturn(PETSC_SUCCESS);
4457 }
4458 
4459 /*@C
4460   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4461 
4462   Not Collective
4463 
4464   Input Parameter:
4465 . mat - the matrix, must be a factored matrix
4466 
4467   Output Parameter:
4468 . type - the string name of the package (do not free this string)
4469 
4470   Level: intermediate
4471 
4472   Fortran Notes:
4473   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4474 
4475 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4476 @*/
4477 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4478 {
4479   PetscErrorCode (*conv)(Mat, MatSolverType *);
4480 
4481   PetscFunctionBegin;
4482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4483   PetscValidType(mat, 1);
4484   PetscAssertPointer(type, 2);
4485   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4486   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4487   if (conv) PetscCall((*conv)(mat, type));
4488   else *type = MATSOLVERPETSC;
4489   PetscFunctionReturn(PETSC_SUCCESS);
4490 }
4491 
4492 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4493 struct _MatSolverTypeForSpecifcType {
4494   MatType mtype;
4495   /* no entry for MAT_FACTOR_NONE */
4496   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4497   MatSolverTypeForSpecifcType next;
4498 };
4499 
4500 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4501 struct _MatSolverTypeHolder {
4502   char                       *name;
4503   MatSolverTypeForSpecifcType handlers;
4504   MatSolverTypeHolder         next;
4505 };
4506 
4507 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4508 
4509 /*@C
4510   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4511 
4512   Input Parameters:
4513 + package      - name of the package, for example petsc or superlu
4514 . mtype        - the matrix type that works with this package
4515 . ftype        - the type of factorization supported by the package
4516 - createfactor - routine that will create the factored matrix ready to be used
4517 
4518   Level: developer
4519 
4520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4521 @*/
4522 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4523 {
4524   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4525   PetscBool                   flg;
4526   MatSolverTypeForSpecifcType inext, iprev = NULL;
4527 
4528   PetscFunctionBegin;
4529   PetscCall(MatInitializePackage());
4530   if (!next) {
4531     PetscCall(PetscNew(&MatSolverTypeHolders));
4532     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4533     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4534     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4535     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4536     PetscFunctionReturn(PETSC_SUCCESS);
4537   }
4538   while (next) {
4539     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4540     if (flg) {
4541       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4542       inext = next->handlers;
4543       while (inext) {
4544         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4545         if (flg) {
4546           inext->createfactor[(int)ftype - 1] = createfactor;
4547           PetscFunctionReturn(PETSC_SUCCESS);
4548         }
4549         iprev = inext;
4550         inext = inext->next;
4551       }
4552       PetscCall(PetscNew(&iprev->next));
4553       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4554       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4555       PetscFunctionReturn(PETSC_SUCCESS);
4556     }
4557     prev = next;
4558     next = next->next;
4559   }
4560   PetscCall(PetscNew(&prev->next));
4561   PetscCall(PetscStrallocpy(package, &prev->next->name));
4562   PetscCall(PetscNew(&prev->next->handlers));
4563   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4564   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4565   PetscFunctionReturn(PETSC_SUCCESS);
4566 }
4567 
4568 /*@C
4569   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4570 
4571   Input Parameters:
4572 + type  - name of the package, for example petsc or superlu
4573 . ftype - the type of factorization supported by the type
4574 - mtype - the matrix type that works with this type
4575 
4576   Output Parameters:
4577 + foundtype    - `PETSC_TRUE` if the type was registered
4578 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4579 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4580 
4581   Level: developer
4582 
4583 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4584 @*/
4585 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4586 {
4587   MatSolverTypeHolder         next = MatSolverTypeHolders;
4588   PetscBool                   flg;
4589   MatSolverTypeForSpecifcType inext;
4590 
4591   PetscFunctionBegin;
4592   if (foundtype) *foundtype = PETSC_FALSE;
4593   if (foundmtype) *foundmtype = PETSC_FALSE;
4594   if (createfactor) *createfactor = NULL;
4595 
4596   if (type) {
4597     while (next) {
4598       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4599       if (flg) {
4600         if (foundtype) *foundtype = PETSC_TRUE;
4601         inext = next->handlers;
4602         while (inext) {
4603           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4604           if (flg) {
4605             if (foundmtype) *foundmtype = PETSC_TRUE;
4606             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4607             PetscFunctionReturn(PETSC_SUCCESS);
4608           }
4609           inext = inext->next;
4610         }
4611       }
4612       next = next->next;
4613     }
4614   } else {
4615     while (next) {
4616       inext = next->handlers;
4617       while (inext) {
4618         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4619         if (flg && inext->createfactor[(int)ftype - 1]) {
4620           if (foundtype) *foundtype = PETSC_TRUE;
4621           if (foundmtype) *foundmtype = PETSC_TRUE;
4622           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4623           PetscFunctionReturn(PETSC_SUCCESS);
4624         }
4625         inext = inext->next;
4626       }
4627       next = next->next;
4628     }
4629     /* try with base classes inext->mtype */
4630     next = MatSolverTypeHolders;
4631     while (next) {
4632       inext = next->handlers;
4633       while (inext) {
4634         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4635         if (flg && inext->createfactor[(int)ftype - 1]) {
4636           if (foundtype) *foundtype = PETSC_TRUE;
4637           if (foundmtype) *foundmtype = PETSC_TRUE;
4638           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4639           PetscFunctionReturn(PETSC_SUCCESS);
4640         }
4641         inext = inext->next;
4642       }
4643       next = next->next;
4644     }
4645   }
4646   PetscFunctionReturn(PETSC_SUCCESS);
4647 }
4648 
4649 PetscErrorCode MatSolverTypeDestroy(void)
4650 {
4651   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4652   MatSolverTypeForSpecifcType inext, iprev;
4653 
4654   PetscFunctionBegin;
4655   while (next) {
4656     PetscCall(PetscFree(next->name));
4657     inext = next->handlers;
4658     while (inext) {
4659       PetscCall(PetscFree(inext->mtype));
4660       iprev = inext;
4661       inext = inext->next;
4662       PetscCall(PetscFree(iprev));
4663     }
4664     prev = next;
4665     next = next->next;
4666     PetscCall(PetscFree(prev));
4667   }
4668   MatSolverTypeHolders = NULL;
4669   PetscFunctionReturn(PETSC_SUCCESS);
4670 }
4671 
4672 /*@C
4673   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4674 
4675   Logically Collective
4676 
4677   Input Parameter:
4678 . mat - the matrix
4679 
4680   Output Parameter:
4681 . flg - `PETSC_TRUE` if uses the ordering
4682 
4683   Level: developer
4684 
4685   Note:
4686   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4687   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4688 
4689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4690 @*/
4691 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4692 {
4693   PetscFunctionBegin;
4694   *flg = mat->canuseordering;
4695   PetscFunctionReturn(PETSC_SUCCESS);
4696 }
4697 
4698 /*@C
4699   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4700 
4701   Logically Collective
4702 
4703   Input Parameters:
4704 + mat   - the matrix obtained with `MatGetFactor()`
4705 - ftype - the factorization type to be used
4706 
4707   Output Parameter:
4708 . otype - the preferred ordering type
4709 
4710   Level: developer
4711 
4712 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4713 @*/
4714 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4715 {
4716   PetscFunctionBegin;
4717   *otype = mat->preferredordering[ftype];
4718   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4719   PetscFunctionReturn(PETSC_SUCCESS);
4720 }
4721 
4722 /*@C
4723   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4724 
4725   Collective
4726 
4727   Input Parameters:
4728 + mat   - the matrix
4729 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4730 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4731 
4732   Output Parameter:
4733 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4734 
4735   Options Database Key:
4736 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4737                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4738 
4739   Level: intermediate
4740 
4741   Notes:
4742   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4743   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4744 
4745   Users usually access the factorization solvers via `KSP`
4746 
4747   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4748   such as pastix, superlu, mumps etc.
4749 
4750   PETSc must have been ./configure to use the external solver, using the option --download-package
4751 
4752   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4753   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4754   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4755 
4756   Developer Notes:
4757   This should actually be called `MatCreateFactor()` since it creates a new factor object
4758 
4759 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4760           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4761 @*/
4762 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4763 {
4764   PetscBool foundtype, foundmtype;
4765   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4766 
4767   PetscFunctionBegin;
4768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4769   PetscValidType(mat, 1);
4770 
4771   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4772   MatCheckPreallocated(mat, 1);
4773 
4774   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4775   if (!foundtype) {
4776     if (type) {
4777       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],
4778               ((PetscObject)mat)->type_name, type);
4779     } else {
4780       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);
4781     }
4782   }
4783   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4784   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);
4785 
4786   PetscCall((*conv)(mat, ftype, f));
4787   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4788   PetscFunctionReturn(PETSC_SUCCESS);
4789 }
4790 
4791 /*@C
4792   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4793 
4794   Not Collective
4795 
4796   Input Parameters:
4797 + mat   - the matrix
4798 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4799 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4800 
4801   Output Parameter:
4802 . flg - PETSC_TRUE if the factorization is available
4803 
4804   Level: intermediate
4805 
4806   Notes:
4807   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4808   such as pastix, superlu, mumps etc.
4809 
4810   PETSc must have been ./configure to use the external solver, using the option --download-package
4811 
4812   Developer Notes:
4813   This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4814 
4815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4816           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4817 @*/
4818 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4819 {
4820   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4821 
4822   PetscFunctionBegin;
4823   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4824   PetscAssertPointer(flg, 4);
4825 
4826   *flg = PETSC_FALSE;
4827   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4828 
4829   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4830   MatCheckPreallocated(mat, 1);
4831 
4832   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4833   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4834   PetscFunctionReturn(PETSC_SUCCESS);
4835 }
4836 
4837 /*@
4838   MatDuplicate - Duplicates a matrix including the non-zero structure.
4839 
4840   Collective
4841 
4842   Input Parameters:
4843 + mat - the matrix
4844 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4845         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4846 
4847   Output Parameter:
4848 . M - pointer to place new matrix
4849 
4850   Level: intermediate
4851 
4852   Notes:
4853   You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4854 
4855   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.
4856 
4857   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
4858   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4859   User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4860 
4861 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4862 @*/
4863 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4864 {
4865   Mat         B;
4866   VecType     vtype;
4867   PetscInt    i;
4868   PetscObject dm, container_h, container_d;
4869   void (*viewf)(void);
4870 
4871   PetscFunctionBegin;
4872   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4873   PetscValidType(mat, 1);
4874   PetscAssertPointer(M, 3);
4875   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4876   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4877   MatCheckPreallocated(mat, 1);
4878 
4879   *M = NULL;
4880   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4881   PetscUseTypeMethod(mat, duplicate, op, M);
4882   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4883   B = *M;
4884 
4885   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4886   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4887   PetscCall(MatGetVecType(mat, &vtype));
4888   PetscCall(MatSetVecType(B, vtype));
4889 
4890   B->stencil.dim = mat->stencil.dim;
4891   B->stencil.noc = mat->stencil.noc;
4892   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4893     B->stencil.dims[i]   = mat->stencil.dims[i];
4894     B->stencil.starts[i] = mat->stencil.starts[i];
4895   }
4896 
4897   B->nooffproczerorows = mat->nooffproczerorows;
4898   B->nooffprocentries  = mat->nooffprocentries;
4899 
4900   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4901   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4902   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4903   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4904   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4905   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4906   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4907   PetscFunctionReturn(PETSC_SUCCESS);
4908 }
4909 
4910 /*@
4911   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4912 
4913   Logically Collective
4914 
4915   Input Parameter:
4916 . mat - the matrix
4917 
4918   Output Parameter:
4919 . v - the diagonal of the matrix
4920 
4921   Level: intermediate
4922 
4923   Note:
4924   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4925   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4926   is larger than `ndiag`, the values of the remaining entries are unspecified.
4927 
4928   Currently only correct in parallel for square matrices.
4929 
4930 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4931 @*/
4932 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4933 {
4934   PetscFunctionBegin;
4935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4936   PetscValidType(mat, 1);
4937   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4938   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4939   MatCheckPreallocated(mat, 1);
4940   if (PetscDefined(USE_DEBUG)) {
4941     PetscInt nv, row, col, ndiag;
4942 
4943     PetscCall(VecGetLocalSize(v, &nv));
4944     PetscCall(MatGetLocalSize(mat, &row, &col));
4945     ndiag = PetscMin(row, col);
4946     PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag);
4947   }
4948 
4949   PetscUseTypeMethod(mat, getdiagonal, v);
4950   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4951   PetscFunctionReturn(PETSC_SUCCESS);
4952 }
4953 
4954 /*@C
4955   MatGetRowMin - Gets the minimum value (of the real part) of each
4956   row of the matrix
4957 
4958   Logically Collective
4959 
4960   Input Parameter:
4961 . mat - the matrix
4962 
4963   Output Parameters:
4964 + v   - the vector for storing the maximums
4965 - idx - the indices of the column found for each row (optional)
4966 
4967   Level: intermediate
4968 
4969   Note:
4970   The result of this call are the same as if one converted the matrix to dense format
4971   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4972 
4973   This code is only implemented for a couple of matrix formats.
4974 
4975 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4976           `MatGetRowMax()`
4977 @*/
4978 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4979 {
4980   PetscFunctionBegin;
4981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4982   PetscValidType(mat, 1);
4983   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4984   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4985 
4986   if (!mat->cmap->N) {
4987     PetscCall(VecSet(v, PETSC_MAX_REAL));
4988     if (idx) {
4989       PetscInt i, m = mat->rmap->n;
4990       for (i = 0; i < m; i++) idx[i] = -1;
4991     }
4992   } else {
4993     MatCheckPreallocated(mat, 1);
4994   }
4995   PetscUseTypeMethod(mat, getrowmin, v, idx);
4996   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4997   PetscFunctionReturn(PETSC_SUCCESS);
4998 }
4999 
5000 /*@C
5001   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5002   row of the matrix
5003 
5004   Logically Collective
5005 
5006   Input Parameter:
5007 . mat - the matrix
5008 
5009   Output Parameters:
5010 + v   - the vector for storing the minimums
5011 - idx - the indices of the column found for each row (or `NULL` if not needed)
5012 
5013   Level: intermediate
5014 
5015   Notes:
5016   if a row is completely empty or has only 0.0 values then the idx[] value for that
5017   row is 0 (the first column).
5018 
5019   This code is only implemented for a couple of matrix formats.
5020 
5021 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5022 @*/
5023 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5024 {
5025   PetscFunctionBegin;
5026   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5027   PetscValidType(mat, 1);
5028   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5029   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5030   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5031 
5032   if (!mat->cmap->N) {
5033     PetscCall(VecSet(v, 0.0));
5034     if (idx) {
5035       PetscInt i, m = mat->rmap->n;
5036       for (i = 0; i < m; i++) idx[i] = -1;
5037     }
5038   } else {
5039     MatCheckPreallocated(mat, 1);
5040     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5041     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5042   }
5043   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5044   PetscFunctionReturn(PETSC_SUCCESS);
5045 }
5046 
5047 /*@C
5048   MatGetRowMax - Gets the maximum value (of the real part) of each
5049   row of the matrix
5050 
5051   Logically Collective
5052 
5053   Input Parameter:
5054 . mat - the matrix
5055 
5056   Output Parameters:
5057 + v   - the vector for storing the maximums
5058 - idx - the indices of the column found for each row (optional)
5059 
5060   Level: intermediate
5061 
5062   Notes:
5063   The result of this call are the same as if one converted the matrix to dense format
5064   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5065 
5066   This code is only implemented for a couple of matrix formats.
5067 
5068 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5069 @*/
5070 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5071 {
5072   PetscFunctionBegin;
5073   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5074   PetscValidType(mat, 1);
5075   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5076   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5077 
5078   if (!mat->cmap->N) {
5079     PetscCall(VecSet(v, PETSC_MIN_REAL));
5080     if (idx) {
5081       PetscInt i, m = mat->rmap->n;
5082       for (i = 0; i < m; i++) idx[i] = -1;
5083     }
5084   } else {
5085     MatCheckPreallocated(mat, 1);
5086     PetscUseTypeMethod(mat, getrowmax, v, idx);
5087   }
5088   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5089   PetscFunctionReturn(PETSC_SUCCESS);
5090 }
5091 
5092 /*@C
5093   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5094   row of the matrix
5095 
5096   Logically Collective
5097 
5098   Input Parameter:
5099 . mat - the matrix
5100 
5101   Output Parameters:
5102 + v   - the vector for storing the maximums
5103 - idx - the indices of the column found for each row (or `NULL` if not needed)
5104 
5105   Level: intermediate
5106 
5107   Notes:
5108   if a row is completely empty or has only 0.0 values then the idx[] value for that
5109   row is 0 (the first column).
5110 
5111   This code is only implemented for a couple of matrix formats.
5112 
5113 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5114 @*/
5115 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
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 
5123   if (!mat->cmap->N) {
5124     PetscCall(VecSet(v, 0.0));
5125     if (idx) {
5126       PetscInt i, m = mat->rmap->n;
5127       for (i = 0; i < m; i++) idx[i] = -1;
5128     }
5129   } else {
5130     MatCheckPreallocated(mat, 1);
5131     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5132     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5133   }
5134   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5135   PetscFunctionReturn(PETSC_SUCCESS);
5136 }
5137 
5138 /*@
5139   MatGetRowSum - Gets the sum of each row of the matrix
5140 
5141   Logically or Neighborhood Collective
5142 
5143   Input Parameter:
5144 . mat - the matrix
5145 
5146   Output Parameter:
5147 . v - the vector for storing the sum of rows
5148 
5149   Level: intermediate
5150 
5151   Notes:
5152   This code is slow since it is not currently specialized for different formats
5153 
5154 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5155 @*/
5156 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5157 {
5158   Vec ones;
5159 
5160   PetscFunctionBegin;
5161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5162   PetscValidType(mat, 1);
5163   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5164   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5165   MatCheckPreallocated(mat, 1);
5166   PetscCall(MatCreateVecs(mat, &ones, NULL));
5167   PetscCall(VecSet(ones, 1.));
5168   PetscCall(MatMult(mat, ones, v));
5169   PetscCall(VecDestroy(&ones));
5170   PetscFunctionReturn(PETSC_SUCCESS);
5171 }
5172 
5173 /*@
5174   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5175   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5176 
5177   Collective
5178 
5179   Input Parameter:
5180 . mat - the matrix to provide the transpose
5181 
5182   Output Parameter:
5183 . B - 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
5184 
5185   Level: advanced
5186 
5187   Note:
5188   Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5189   routine allows bypassing that call.
5190 
5191 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5192 @*/
5193 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5194 {
5195   PetscContainer  rB = NULL;
5196   MatParentState *rb = NULL;
5197 
5198   PetscFunctionBegin;
5199   PetscCall(PetscNew(&rb));
5200   rb->id    = ((PetscObject)mat)->id;
5201   rb->state = 0;
5202   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5203   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5204   PetscCall(PetscContainerSetPointer(rB, rb));
5205   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5206   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5207   PetscCall(PetscObjectDereference((PetscObject)rB));
5208   PetscFunctionReturn(PETSC_SUCCESS);
5209 }
5210 
5211 /*@
5212   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5213 
5214   Collective
5215 
5216   Input Parameters:
5217 + mat   - the matrix to transpose
5218 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5219 
5220   Output Parameter:
5221 . B - the transpose
5222 
5223   Level: intermediate
5224 
5225   Notes:
5226   If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5227 
5228   `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
5229   transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5230 
5231   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.
5232 
5233   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5234 
5235   If mat is unchanged from the last call this function returns immediately without recomputing the result
5236 
5237   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5238 
5239 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5240           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5241 @*/
5242 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5243 {
5244   PetscContainer  rB = NULL;
5245   MatParentState *rb = NULL;
5246 
5247   PetscFunctionBegin;
5248   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5249   PetscValidType(mat, 1);
5250   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5251   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5252   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5253   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5254   MatCheckPreallocated(mat, 1);
5255   if (reuse == MAT_REUSE_MATRIX) {
5256     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5257     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5258     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5259     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5260     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5261   }
5262 
5263   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5264   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5265     PetscUseTypeMethod(mat, transpose, reuse, B);
5266     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5267   }
5268   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5269 
5270   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5271   if (reuse != MAT_INPLACE_MATRIX) {
5272     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5273     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5274     rb->state        = ((PetscObject)mat)->state;
5275     rb->nonzerostate = mat->nonzerostate;
5276   }
5277   PetscFunctionReturn(PETSC_SUCCESS);
5278 }
5279 
5280 /*@
5281   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5282 
5283   Collective
5284 
5285   Input Parameter:
5286 . A - the matrix to transpose
5287 
5288   Output Parameter:
5289 . 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
5290       numerical portion.
5291 
5292   Level: intermediate
5293 
5294   Note:
5295   This is not supported for many matrix types, use `MatTranspose()` in those cases
5296 
5297 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5298 @*/
5299 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5300 {
5301   PetscFunctionBegin;
5302   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5303   PetscValidType(A, 1);
5304   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5305   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5306   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5307   PetscUseTypeMethod(A, transposesymbolic, B);
5308   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5309 
5310   PetscCall(MatTransposeSetPrecursor(A, *B));
5311   PetscFunctionReturn(PETSC_SUCCESS);
5312 }
5313 
5314 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5315 {
5316   PetscContainer  rB;
5317   MatParentState *rb;
5318 
5319   PetscFunctionBegin;
5320   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5321   PetscValidType(A, 1);
5322   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5323   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5324   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5325   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5326   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5327   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5328   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5329   PetscFunctionReturn(PETSC_SUCCESS);
5330 }
5331 
5332 /*@
5333   MatIsTranspose - Test whether a matrix is another one's transpose,
5334   or its own, in which case it tests symmetry.
5335 
5336   Collective
5337 
5338   Input Parameters:
5339 + A   - the matrix to test
5340 . B   - the matrix to test against, this can equal the first parameter
5341 - tol - tolerance, differences between entries smaller than this are counted as zero
5342 
5343   Output Parameter:
5344 . flg - the result
5345 
5346   Level: intermediate
5347 
5348   Notes:
5349   Only available for `MATAIJ` matrices.
5350 
5351   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5352   test involves parallel copies of the block off-diagonal parts of the matrix.
5353 
5354 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5355 @*/
5356 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5357 {
5358   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5359 
5360   PetscFunctionBegin;
5361   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5362   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5363   PetscAssertPointer(flg, 4);
5364   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5365   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5366   *flg = PETSC_FALSE;
5367   if (f && g) {
5368     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5369     PetscCall((*f)(A, B, tol, flg));
5370   } else {
5371     MatType mattype;
5372 
5373     PetscCall(MatGetType(f ? B : A, &mattype));
5374     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5375   }
5376   PetscFunctionReturn(PETSC_SUCCESS);
5377 }
5378 
5379 /*@
5380   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5381 
5382   Collective
5383 
5384   Input Parameters:
5385 + mat   - the matrix to transpose and complex conjugate
5386 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5387 
5388   Output Parameter:
5389 . B - the Hermitian transpose
5390 
5391   Level: intermediate
5392 
5393 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5394 @*/
5395 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5396 {
5397   PetscFunctionBegin;
5398   PetscCall(MatTranspose(mat, reuse, B));
5399 #if defined(PETSC_USE_COMPLEX)
5400   PetscCall(MatConjugate(*B));
5401 #endif
5402   PetscFunctionReturn(PETSC_SUCCESS);
5403 }
5404 
5405 /*@
5406   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5407 
5408   Collective
5409 
5410   Input Parameters:
5411 + A   - the matrix to test
5412 . B   - the matrix to test against, this can equal the first parameter
5413 - tol - tolerance, differences between entries smaller than this are counted as zero
5414 
5415   Output Parameter:
5416 . flg - the result
5417 
5418   Level: intermediate
5419 
5420   Notes:
5421   Only available for `MATAIJ` matrices.
5422 
5423   The sequential algorithm
5424   has a running time of the order of the number of nonzeros; the parallel
5425   test involves parallel copies of the block off-diagonal parts of the matrix.
5426 
5427 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5428 @*/
5429 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5430 {
5431   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5432 
5433   PetscFunctionBegin;
5434   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5435   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5436   PetscAssertPointer(flg, 4);
5437   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5438   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5439   if (f && g) {
5440     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5441     PetscCall((*f)(A, B, tol, flg));
5442   }
5443   PetscFunctionReturn(PETSC_SUCCESS);
5444 }
5445 
5446 /*@
5447   MatPermute - Creates a new matrix with rows and columns permuted from the
5448   original.
5449 
5450   Collective
5451 
5452   Input Parameters:
5453 + mat - the matrix to permute
5454 . row - row permutation, each processor supplies only the permutation for its rows
5455 - col - column permutation, each processor supplies only the permutation for its columns
5456 
5457   Output Parameter:
5458 . B - the permuted matrix
5459 
5460   Level: advanced
5461 
5462   Note:
5463   The index sets map from row/col of permuted matrix to row/col of original matrix.
5464   The index sets should be on the same communicator as mat and have the same local sizes.
5465 
5466   Developer Notes:
5467   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5468   exploit the fact that row and col are permutations, consider implementing the
5469   more general `MatCreateSubMatrix()` instead.
5470 
5471 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5472 @*/
5473 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5474 {
5475   PetscFunctionBegin;
5476   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5477   PetscValidType(mat, 1);
5478   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5479   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5480   PetscAssertPointer(B, 4);
5481   PetscCheckSameComm(mat, 1, row, 2);
5482   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5483   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5484   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5485   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5486   MatCheckPreallocated(mat, 1);
5487 
5488   if (mat->ops->permute) {
5489     PetscUseTypeMethod(mat, permute, row, col, B);
5490     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5491   } else {
5492     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5493   }
5494   PetscFunctionReturn(PETSC_SUCCESS);
5495 }
5496 
5497 /*@
5498   MatEqual - Compares two matrices.
5499 
5500   Collective
5501 
5502   Input Parameters:
5503 + A - the first matrix
5504 - B - the second matrix
5505 
5506   Output Parameter:
5507 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5508 
5509   Level: intermediate
5510 
5511 .seealso: [](ch_matrices), `Mat`
5512 @*/
5513 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5514 {
5515   PetscFunctionBegin;
5516   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5517   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5518   PetscValidType(A, 1);
5519   PetscValidType(B, 2);
5520   PetscAssertPointer(flg, 3);
5521   PetscCheckSameComm(A, 1, B, 2);
5522   MatCheckPreallocated(A, 1);
5523   MatCheckPreallocated(B, 2);
5524   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5525   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5526   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,
5527              B->cmap->N);
5528   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5529     PetscUseTypeMethod(A, equal, B, flg);
5530   } else {
5531     PetscCall(MatMultEqual(A, B, 10, flg));
5532   }
5533   PetscFunctionReturn(PETSC_SUCCESS);
5534 }
5535 
5536 /*@
5537   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5538   matrices that are stored as vectors.  Either of the two scaling
5539   matrices can be `NULL`.
5540 
5541   Collective
5542 
5543   Input Parameters:
5544 + mat - the matrix to be scaled
5545 . l   - the left scaling vector (or `NULL`)
5546 - r   - the right scaling vector (or `NULL`)
5547 
5548   Level: intermediate
5549 
5550   Note:
5551   `MatDiagonalScale()` computes A = LAR, where
5552   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5553   The L scales the rows of the matrix, the R scales the columns of the matrix.
5554 
5555 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5556 @*/
5557 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5558 {
5559   PetscFunctionBegin;
5560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5561   PetscValidType(mat, 1);
5562   if (l) {
5563     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5564     PetscCheckSameComm(mat, 1, l, 2);
5565   }
5566   if (r) {
5567     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5568     PetscCheckSameComm(mat, 1, r, 3);
5569   }
5570   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5571   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5572   MatCheckPreallocated(mat, 1);
5573   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5574 
5575   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5576   PetscUseTypeMethod(mat, diagonalscale, l, r);
5577   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5578   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5579   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5580   PetscFunctionReturn(PETSC_SUCCESS);
5581 }
5582 
5583 /*@
5584   MatScale - Scales all elements of a matrix by a given number.
5585 
5586   Logically Collective
5587 
5588   Input Parameters:
5589 + mat - the matrix to be scaled
5590 - a   - the scaling value
5591 
5592   Level: intermediate
5593 
5594 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5595 @*/
5596 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5597 {
5598   PetscFunctionBegin;
5599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5600   PetscValidType(mat, 1);
5601   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5602   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5603   PetscValidLogicalCollectiveScalar(mat, a, 2);
5604   MatCheckPreallocated(mat, 1);
5605 
5606   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5607   if (a != (PetscScalar)1.0) {
5608     PetscUseTypeMethod(mat, scale, a);
5609     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5610   }
5611   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5612   PetscFunctionReturn(PETSC_SUCCESS);
5613 }
5614 
5615 /*@
5616   MatNorm - Calculates various norms of a matrix.
5617 
5618   Collective
5619 
5620   Input Parameters:
5621 + mat  - the matrix
5622 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5623 
5624   Output Parameter:
5625 . nrm - the resulting norm
5626 
5627   Level: intermediate
5628 
5629 .seealso: [](ch_matrices), `Mat`
5630 @*/
5631 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5632 {
5633   PetscFunctionBegin;
5634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5635   PetscValidType(mat, 1);
5636   PetscAssertPointer(nrm, 3);
5637 
5638   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5639   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5640   MatCheckPreallocated(mat, 1);
5641 
5642   PetscUseTypeMethod(mat, norm, type, nrm);
5643   PetscFunctionReturn(PETSC_SUCCESS);
5644 }
5645 
5646 /*
5647      This variable is used to prevent counting of MatAssemblyBegin() that
5648    are called from within a MatAssemblyEnd().
5649 */
5650 static PetscInt MatAssemblyEnd_InUse = 0;
5651 /*@
5652   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5653   be called after completing all calls to `MatSetValues()`.
5654 
5655   Collective
5656 
5657   Input Parameters:
5658 + mat  - the matrix
5659 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5660 
5661   Level: beginner
5662 
5663   Notes:
5664   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5665   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5666 
5667   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5668   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5669   using the matrix.
5670 
5671   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5672   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
5673   a global collective operation requiring all processes that share the matrix.
5674 
5675   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5676   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5677   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5678 
5679 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5680 @*/
5681 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5682 {
5683   PetscFunctionBegin;
5684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5685   PetscValidType(mat, 1);
5686   MatCheckPreallocated(mat, 1);
5687   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5688   if (mat->assembled) {
5689     mat->was_assembled = PETSC_TRUE;
5690     mat->assembled     = PETSC_FALSE;
5691   }
5692 
5693   if (!MatAssemblyEnd_InUse) {
5694     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5695     PetscTryTypeMethod(mat, assemblybegin, type);
5696     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5697   } else PetscTryTypeMethod(mat, assemblybegin, type);
5698   PetscFunctionReturn(PETSC_SUCCESS);
5699 }
5700 
5701 /*@
5702   MatAssembled - Indicates if a matrix has been assembled and is ready for
5703   use; for example, in matrix-vector product.
5704 
5705   Not Collective
5706 
5707   Input Parameter:
5708 . mat - the matrix
5709 
5710   Output Parameter:
5711 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5712 
5713   Level: advanced
5714 
5715 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5716 @*/
5717 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5718 {
5719   PetscFunctionBegin;
5720   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5721   PetscAssertPointer(assembled, 2);
5722   *assembled = mat->assembled;
5723   PetscFunctionReturn(PETSC_SUCCESS);
5724 }
5725 
5726 /*@
5727   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5728   be called after `MatAssemblyBegin()`.
5729 
5730   Collective
5731 
5732   Input Parameters:
5733 + mat  - the matrix
5734 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5735 
5736   Options Database Keys:
5737 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5738 . -mat_view ::ascii_info_detail      - Prints more detailed info
5739 . -mat_view                          - Prints matrix in ASCII format
5740 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5741 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5742 . -display <name>                    - Sets display name (default is host)
5743 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5744 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5745 . -viewer_socket_machine <machine>   - Machine to use for socket
5746 . -viewer_socket_port <port>         - Port number to use for socket
5747 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5748 
5749   Level: beginner
5750 
5751 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5752 @*/
5753 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5754 {
5755   static PetscInt inassm = 0;
5756   PetscBool       flg    = PETSC_FALSE;
5757 
5758   PetscFunctionBegin;
5759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5760   PetscValidType(mat, 1);
5761 
5762   inassm++;
5763   MatAssemblyEnd_InUse++;
5764   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5765     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5766     PetscTryTypeMethod(mat, assemblyend, type);
5767     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5768   } else PetscTryTypeMethod(mat, assemblyend, type);
5769 
5770   /* Flush assembly is not a true assembly */
5771   if (type != MAT_FLUSH_ASSEMBLY) {
5772     if (mat->num_ass) {
5773       if (!mat->symmetry_eternal) {
5774         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5775         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5776       }
5777       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5778       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5779     }
5780     mat->num_ass++;
5781     mat->assembled        = PETSC_TRUE;
5782     mat->ass_nonzerostate = mat->nonzerostate;
5783   }
5784 
5785   mat->insertmode = NOT_SET_VALUES;
5786   MatAssemblyEnd_InUse--;
5787   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5788   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5789     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5790 
5791     if (mat->checksymmetryonassembly) {
5792       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5793       if (flg) {
5794         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5795       } else {
5796         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5797       }
5798     }
5799     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5800   }
5801   inassm--;
5802   PetscFunctionReturn(PETSC_SUCCESS);
5803 }
5804 
5805 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5806 /*@
5807   MatSetOption - Sets a parameter option for a matrix. Some options
5808   may be specific to certain storage formats.  Some options
5809   determine how values will be inserted (or added). Sorted,
5810   row-oriented input will generally assemble the fastest. The default
5811   is row-oriented.
5812 
5813   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5814 
5815   Input Parameters:
5816 + mat - the matrix
5817 . op  - the option, one of those listed below (and possibly others),
5818 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5819 
5820   Options Describing Matrix Structure:
5821 + `MAT_SPD`                         - symmetric positive definite
5822 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5823 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5824 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5825 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5826 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5827 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5828 
5829    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5830    do not need to be computed (usually at a high cost)
5831 
5832    Options For Use with `MatSetValues()`:
5833    Insert a logically dense subblock, which can be
5834 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5835 
5836    These options reflect the data you pass in with `MatSetValues()`; it has
5837    nothing to do with how the data is stored internally in the matrix
5838    data structure.
5839 
5840    When (re)assembling a matrix, we can restrict the input for
5841    efficiency/debugging purposes.  These options include
5842 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5843 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5844 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5845 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5846 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5847 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5848         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5849         performance for very large process counts.
5850 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5851         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5852         functions, instead sending only neighbor messages.
5853 
5854   Level: intermediate
5855 
5856   Notes:
5857   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5858 
5859   Some options are relevant only for particular matrix types and
5860   are thus ignored by others.  Other options are not supported by
5861   certain matrix types and will generate an error message if set.
5862 
5863   If using Fortran to compute a matrix, one may need to
5864   use the column-oriented option (or convert to the row-oriented
5865   format).
5866 
5867   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5868   that would generate a new entry in the nonzero structure is instead
5869   ignored.  Thus, if memory has not already been allocated for this particular
5870   data, then the insertion is ignored. For dense matrices, in which
5871   the entire array is allocated, no entries are ever ignored.
5872   Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5873 
5874   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5875   that would generate a new entry in the nonzero structure instead produces
5876   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
5877 
5878   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5879   that would generate a new entry that has not been preallocated will
5880   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5881   only.) This is a useful flag when debugging matrix memory preallocation.
5882   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5883 
5884   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5885   other processors should be dropped, rather than stashed.
5886   This is useful if you know that the "owning" processor is also
5887   always generating the correct matrix entries, so that PETSc need
5888   not transfer duplicate entries generated on another processor.
5889 
5890   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5891   searches during matrix assembly. When this flag is set, the hash table
5892   is created during the first matrix assembly. This hash table is
5893   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5894   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5895   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5896   supported by `MATMPIBAIJ` format only.
5897 
5898   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5899   are kept in the nonzero structure
5900 
5901   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5902   a zero location in the matrix
5903 
5904   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5905 
5906   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5907   zero row routines and thus improves performance for very large process counts.
5908 
5909   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5910   part of the matrix (since they should match the upper triangular part).
5911 
5912   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5913   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5914   with finite difference schemes with non-periodic boundary conditions.
5915 
5916   Developer Notes:
5917   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5918   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5919   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5920   not changed.
5921 
5922 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5923 @*/
5924 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5925 {
5926   PetscFunctionBegin;
5927   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5928   if (op > 0) {
5929     PetscValidLogicalCollectiveEnum(mat, op, 2);
5930     PetscValidLogicalCollectiveBool(mat, flg, 3);
5931   }
5932 
5933   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);
5934 
5935   switch (op) {
5936   case MAT_FORCE_DIAGONAL_ENTRIES:
5937     mat->force_diagonals = flg;
5938     PetscFunctionReturn(PETSC_SUCCESS);
5939   case MAT_NO_OFF_PROC_ENTRIES:
5940     mat->nooffprocentries = flg;
5941     PetscFunctionReturn(PETSC_SUCCESS);
5942   case MAT_SUBSET_OFF_PROC_ENTRIES:
5943     mat->assembly_subset = flg;
5944     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5945 #if !defined(PETSC_HAVE_MPIUNI)
5946       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5947 #endif
5948       mat->stash.first_assembly_done = PETSC_FALSE;
5949     }
5950     PetscFunctionReturn(PETSC_SUCCESS);
5951   case MAT_NO_OFF_PROC_ZERO_ROWS:
5952     mat->nooffproczerorows = flg;
5953     PetscFunctionReturn(PETSC_SUCCESS);
5954   case MAT_SPD:
5955     if (flg) {
5956       mat->spd                    = PETSC_BOOL3_TRUE;
5957       mat->symmetric              = PETSC_BOOL3_TRUE;
5958       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5959     } else {
5960       mat->spd = PETSC_BOOL3_FALSE;
5961     }
5962     break;
5963   case MAT_SYMMETRIC:
5964     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5965     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5966 #if !defined(PETSC_USE_COMPLEX)
5967     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5968 #endif
5969     break;
5970   case MAT_HERMITIAN:
5971     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5972     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5973 #if !defined(PETSC_USE_COMPLEX)
5974     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5975 #endif
5976     break;
5977   case MAT_STRUCTURALLY_SYMMETRIC:
5978     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5979     break;
5980   case MAT_SYMMETRY_ETERNAL:
5981     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");
5982     mat->symmetry_eternal = flg;
5983     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5984     break;
5985   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5986     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false");
5987     mat->structural_symmetry_eternal = flg;
5988     break;
5989   case MAT_SPD_ETERNAL:
5990     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");
5991     mat->spd_eternal = flg;
5992     if (flg) {
5993       mat->structural_symmetry_eternal = PETSC_TRUE;
5994       mat->symmetry_eternal            = PETSC_TRUE;
5995     }
5996     break;
5997   case MAT_STRUCTURE_ONLY:
5998     mat->structure_only = flg;
5999     break;
6000   case MAT_SORTED_FULL:
6001     mat->sortedfull = flg;
6002     break;
6003   default:
6004     break;
6005   }
6006   PetscTryTypeMethod(mat, setoption, op, flg);
6007   PetscFunctionReturn(PETSC_SUCCESS);
6008 }
6009 
6010 /*@
6011   MatGetOption - Gets a parameter option that has been set for a matrix.
6012 
6013   Logically Collective
6014 
6015   Input Parameters:
6016 + mat - the matrix
6017 - op  - the option, this only responds to certain options, check the code for which ones
6018 
6019   Output Parameter:
6020 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6021 
6022   Level: intermediate
6023 
6024   Notes:
6025   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6026 
6027   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6028   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6029 
6030 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6031     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6032 @*/
6033 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6034 {
6035   PetscFunctionBegin;
6036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6037   PetscValidType(mat, 1);
6038 
6039   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);
6040   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()");
6041 
6042   switch (op) {
6043   case MAT_NO_OFF_PROC_ENTRIES:
6044     *flg = mat->nooffprocentries;
6045     break;
6046   case MAT_NO_OFF_PROC_ZERO_ROWS:
6047     *flg = mat->nooffproczerorows;
6048     break;
6049   case MAT_SYMMETRIC:
6050     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6051     break;
6052   case MAT_HERMITIAN:
6053     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6054     break;
6055   case MAT_STRUCTURALLY_SYMMETRIC:
6056     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6057     break;
6058   case MAT_SPD:
6059     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6060     break;
6061   case MAT_SYMMETRY_ETERNAL:
6062     *flg = mat->symmetry_eternal;
6063     break;
6064   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6065     *flg = mat->symmetry_eternal;
6066     break;
6067   default:
6068     break;
6069   }
6070   PetscFunctionReturn(PETSC_SUCCESS);
6071 }
6072 
6073 /*@
6074   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6075   this routine retains the old nonzero structure.
6076 
6077   Logically Collective
6078 
6079   Input Parameter:
6080 . mat - the matrix
6081 
6082   Level: intermediate
6083 
6084   Note:
6085   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.
6086   See the Performance chapter of the users manual for information on preallocating matrices.
6087 
6088 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6089 @*/
6090 PetscErrorCode MatZeroEntries(Mat mat)
6091 {
6092   PetscFunctionBegin;
6093   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6094   PetscValidType(mat, 1);
6095   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6096   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");
6097   MatCheckPreallocated(mat, 1);
6098 
6099   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6100   PetscUseTypeMethod(mat, zeroentries);
6101   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6102   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6103   PetscFunctionReturn(PETSC_SUCCESS);
6104 }
6105 
6106 /*@
6107   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6108   of a set of rows and columns of a matrix.
6109 
6110   Collective
6111 
6112   Input Parameters:
6113 + mat     - the matrix
6114 . numRows - the number of rows/columns to zero
6115 . rows    - the global row indices
6116 . diag    - value put in the diagonal of the eliminated rows
6117 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6118 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6119 
6120   Level: intermediate
6121 
6122   Notes:
6123   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6124 
6125   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6126   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
6127 
6128   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6129   Krylov method to take advantage of the known solution on the zeroed rows.
6130 
6131   For the parallel case, all processes that share the matrix (i.e.,
6132   those in the communicator used for matrix creation) MUST call this
6133   routine, regardless of whether any rows being zeroed are owned by
6134   them.
6135 
6136   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6137 
6138   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6139   list only rows local to itself).
6140 
6141   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6142 
6143 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6144           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6145 @*/
6146 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6147 {
6148   PetscFunctionBegin;
6149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6150   PetscValidType(mat, 1);
6151   if (numRows) PetscAssertPointer(rows, 3);
6152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6153   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6154   MatCheckPreallocated(mat, 1);
6155 
6156   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6157   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6158   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6159   PetscFunctionReturn(PETSC_SUCCESS);
6160 }
6161 
6162 /*@
6163   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6164   of a set of rows and columns of a matrix.
6165 
6166   Collective
6167 
6168   Input Parameters:
6169 + mat  - the matrix
6170 . is   - the rows to zero
6171 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6172 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6173 - b    - optional vector of right hand side, that will be adjusted by provided solution
6174 
6175   Level: intermediate
6176 
6177   Note:
6178   See `MatZeroRowsColumns()` for details on how this routine operates.
6179 
6180 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6181           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6182 @*/
6183 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6184 {
6185   PetscInt        numRows;
6186   const PetscInt *rows;
6187 
6188   PetscFunctionBegin;
6189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6190   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6191   PetscValidType(mat, 1);
6192   PetscValidType(is, 2);
6193   PetscCall(ISGetLocalSize(is, &numRows));
6194   PetscCall(ISGetIndices(is, &rows));
6195   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6196   PetscCall(ISRestoreIndices(is, &rows));
6197   PetscFunctionReturn(PETSC_SUCCESS);
6198 }
6199 
6200 /*@
6201   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6202   of a set of rows of a matrix.
6203 
6204   Collective
6205 
6206   Input Parameters:
6207 + mat     - the matrix
6208 . numRows - the number of rows to zero
6209 . rows    - the global row indices
6210 . diag    - value put in the diagonal of the zeroed rows
6211 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6212 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6213 
6214   Level: intermediate
6215 
6216   Notes:
6217   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6218 
6219   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6220 
6221   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6222   Krylov method to take advantage of the known solution on the zeroed rows.
6223 
6224   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)
6225   from the matrix.
6226 
6227   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6228   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
6229   formats this does not alter the nonzero structure.
6230 
6231   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6232   of the matrix is not changed the values are
6233   merely zeroed.
6234 
6235   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6236   formats can optionally remove the main diagonal entry from the
6237   nonzero structure as well, by passing 0.0 as the final argument).
6238 
6239   For the parallel case, all processes that share the matrix (i.e.,
6240   those in the communicator used for matrix creation) MUST call this
6241   routine, regardless of whether any rows being zeroed are owned by
6242   them.
6243 
6244   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6245   list only rows local to itself).
6246 
6247   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6248   owns that are to be zeroed. This saves a global synchronization in the implementation.
6249 
6250 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6251           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6252 @*/
6253 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6254 {
6255   PetscFunctionBegin;
6256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6257   PetscValidType(mat, 1);
6258   if (numRows) PetscAssertPointer(rows, 3);
6259   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6260   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6261   MatCheckPreallocated(mat, 1);
6262 
6263   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6264   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6265   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6266   PetscFunctionReturn(PETSC_SUCCESS);
6267 }
6268 
6269 /*@
6270   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6271   of a set of rows of a matrix.
6272 
6273   Collective
6274 
6275   Input Parameters:
6276 + mat  - the matrix
6277 . is   - index set of rows to remove (if `NULL` then no row is removed)
6278 . diag - value put in all diagonals of eliminated rows
6279 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6280 - b    - optional vector of right hand side, that will be adjusted by provided solution
6281 
6282   Level: intermediate
6283 
6284   Note:
6285   See `MatZeroRows()` for details on how this routine operates.
6286 
6287 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6288           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6289 @*/
6290 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6291 {
6292   PetscInt        numRows = 0;
6293   const PetscInt *rows    = NULL;
6294 
6295   PetscFunctionBegin;
6296   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6297   PetscValidType(mat, 1);
6298   if (is) {
6299     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6300     PetscCall(ISGetLocalSize(is, &numRows));
6301     PetscCall(ISGetIndices(is, &rows));
6302   }
6303   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6304   if (is) PetscCall(ISRestoreIndices(is, &rows));
6305   PetscFunctionReturn(PETSC_SUCCESS);
6306 }
6307 
6308 /*@
6309   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6310   of a set of rows of a matrix. These rows must be local to the process.
6311 
6312   Collective
6313 
6314   Input Parameters:
6315 + mat     - the matrix
6316 . numRows - the number of rows to remove
6317 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6318 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6319 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6320 - b       - optional vector of right hand side, that will be adjusted by provided solution
6321 
6322   Level: intermediate
6323 
6324   Notes:
6325   See `MatZeroRows()` for details on how this routine operates.
6326 
6327   The grid coordinates are across the entire grid, not just the local portion
6328 
6329   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6330   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6331   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6332   `DM_BOUNDARY_PERIODIC` boundary type.
6333 
6334   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
6335   a single value per point) you can skip filling those indices.
6336 
6337   Fortran Notes:
6338   `idxm` and `idxn` should be declared as
6339 $     MatStencil idxm(4, m)
6340   and the values inserted using
6341 .vb
6342     idxm(MatStencil_i, 1) = i
6343     idxm(MatStencil_j, 1) = j
6344     idxm(MatStencil_k, 1) = k
6345     idxm(MatStencil_c, 1) = c
6346    etc
6347 .ve
6348 
6349 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6350           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6351 @*/
6352 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6353 {
6354   PetscInt  dim    = mat->stencil.dim;
6355   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6356   PetscInt *dims   = mat->stencil.dims + 1;
6357   PetscInt *starts = mat->stencil.starts;
6358   PetscInt *dxm    = (PetscInt *)rows;
6359   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6360 
6361   PetscFunctionBegin;
6362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6363   PetscValidType(mat, 1);
6364   if (numRows) PetscAssertPointer(rows, 3);
6365 
6366   PetscCall(PetscMalloc1(numRows, &jdxm));
6367   for (i = 0; i < numRows; ++i) {
6368     /* Skip unused dimensions (they are ordered k, j, i, c) */
6369     for (j = 0; j < 3 - sdim; ++j) dxm++;
6370     /* Local index in X dir */
6371     tmp = *dxm++ - starts[0];
6372     /* Loop over remaining dimensions */
6373     for (j = 0; j < dim - 1; ++j) {
6374       /* If nonlocal, set index to be negative */
6375       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6376       /* Update local index */
6377       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6378     }
6379     /* Skip component slot if necessary */
6380     if (mat->stencil.noc) dxm++;
6381     /* Local row number */
6382     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6383   }
6384   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6385   PetscCall(PetscFree(jdxm));
6386   PetscFunctionReturn(PETSC_SUCCESS);
6387 }
6388 
6389 /*@
6390   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6391   of a set of rows and columns of a matrix.
6392 
6393   Collective
6394 
6395   Input Parameters:
6396 + mat     - the matrix
6397 . numRows - the number of rows/columns to remove
6398 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6399 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6400 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6401 - b       - optional vector of right hand side, that will be adjusted by provided solution
6402 
6403   Level: intermediate
6404 
6405   Notes:
6406   See `MatZeroRowsColumns()` for details on how this routine operates.
6407 
6408   The grid coordinates are across the entire grid, not just the local portion
6409 
6410   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6411   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6412   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6413   `DM_BOUNDARY_PERIODIC` boundary type.
6414 
6415   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
6416   a single value per point) you can skip filling those indices.
6417 
6418   Fortran Notes:
6419   `idxm` and `idxn` should be declared as
6420 $     MatStencil idxm(4, m)
6421   and the values inserted using
6422 .vb
6423     idxm(MatStencil_i, 1) = i
6424     idxm(MatStencil_j, 1) = j
6425     idxm(MatStencil_k, 1) = k
6426     idxm(MatStencil_c, 1) = c
6427     etc
6428 .ve
6429 
6430 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6431           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6432 @*/
6433 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6434 {
6435   PetscInt  dim    = mat->stencil.dim;
6436   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6437   PetscInt *dims   = mat->stencil.dims + 1;
6438   PetscInt *starts = mat->stencil.starts;
6439   PetscInt *dxm    = (PetscInt *)rows;
6440   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6441 
6442   PetscFunctionBegin;
6443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6444   PetscValidType(mat, 1);
6445   if (numRows) PetscAssertPointer(rows, 3);
6446 
6447   PetscCall(PetscMalloc1(numRows, &jdxm));
6448   for (i = 0; i < numRows; ++i) {
6449     /* Skip unused dimensions (they are ordered k, j, i, c) */
6450     for (j = 0; j < 3 - sdim; ++j) dxm++;
6451     /* Local index in X dir */
6452     tmp = *dxm++ - starts[0];
6453     /* Loop over remaining dimensions */
6454     for (j = 0; j < dim - 1; ++j) {
6455       /* If nonlocal, set index to be negative */
6456       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6457       /* Update local index */
6458       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6459     }
6460     /* Skip component slot if necessary */
6461     if (mat->stencil.noc) dxm++;
6462     /* Local row number */
6463     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6464   }
6465   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6466   PetscCall(PetscFree(jdxm));
6467   PetscFunctionReturn(PETSC_SUCCESS);
6468 }
6469 
6470 /*@C
6471   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6472   of a set of rows of a matrix; using local numbering of rows.
6473 
6474   Collective
6475 
6476   Input Parameters:
6477 + mat     - the matrix
6478 . numRows - the number of rows to remove
6479 . rows    - the local row indices
6480 . diag    - value put in all diagonals of eliminated rows
6481 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6482 - b       - optional vector of right hand side, that will be adjusted by provided solution
6483 
6484   Level: intermediate
6485 
6486   Notes:
6487   Before calling `MatZeroRowsLocal()`, the user must first set the
6488   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6489 
6490   See `MatZeroRows()` for details on how this routine operates.
6491 
6492 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6493           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6494 @*/
6495 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6496 {
6497   PetscFunctionBegin;
6498   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6499   PetscValidType(mat, 1);
6500   if (numRows) PetscAssertPointer(rows, 3);
6501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6503   MatCheckPreallocated(mat, 1);
6504 
6505   if (mat->ops->zerorowslocal) {
6506     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6507   } else {
6508     IS              is, newis;
6509     const PetscInt *newRows;
6510 
6511     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6512     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6513     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6514     PetscCall(ISGetIndices(newis, &newRows));
6515     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6516     PetscCall(ISRestoreIndices(newis, &newRows));
6517     PetscCall(ISDestroy(&newis));
6518     PetscCall(ISDestroy(&is));
6519   }
6520   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6521   PetscFunctionReturn(PETSC_SUCCESS);
6522 }
6523 
6524 /*@
6525   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6526   of a set of rows of a matrix; using local numbering of rows.
6527 
6528   Collective
6529 
6530   Input Parameters:
6531 + mat  - the matrix
6532 . is   - index set of rows to remove
6533 . diag - value put in all diagonals of eliminated rows
6534 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6535 - b    - optional vector of right hand side, that will be adjusted by provided solution
6536 
6537   Level: intermediate
6538 
6539   Notes:
6540   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6541   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6542 
6543   See `MatZeroRows()` for details on how this routine operates.
6544 
6545 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6546           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6547 @*/
6548 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6549 {
6550   PetscInt        numRows;
6551   const PetscInt *rows;
6552 
6553   PetscFunctionBegin;
6554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6555   PetscValidType(mat, 1);
6556   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6558   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6559   MatCheckPreallocated(mat, 1);
6560 
6561   PetscCall(ISGetLocalSize(is, &numRows));
6562   PetscCall(ISGetIndices(is, &rows));
6563   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6564   PetscCall(ISRestoreIndices(is, &rows));
6565   PetscFunctionReturn(PETSC_SUCCESS);
6566 }
6567 
6568 /*@
6569   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6570   of a set of rows and columns of a matrix; using local numbering of rows.
6571 
6572   Collective
6573 
6574   Input Parameters:
6575 + mat     - the matrix
6576 . numRows - the number of rows to remove
6577 . rows    - the global row indices
6578 . diag    - value put in all diagonals of eliminated rows
6579 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6580 - b       - optional vector of right hand side, that will be adjusted by provided solution
6581 
6582   Level: intermediate
6583 
6584   Notes:
6585   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6586   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6587 
6588   See `MatZeroRowsColumns()` for details on how this routine operates.
6589 
6590 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6591           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6592 @*/
6593 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6594 {
6595   IS              is, newis;
6596   const PetscInt *newRows;
6597 
6598   PetscFunctionBegin;
6599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6600   PetscValidType(mat, 1);
6601   if (numRows) PetscAssertPointer(rows, 3);
6602   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6603   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6604   MatCheckPreallocated(mat, 1);
6605 
6606   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6607   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6608   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6609   PetscCall(ISGetIndices(newis, &newRows));
6610   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6611   PetscCall(ISRestoreIndices(newis, &newRows));
6612   PetscCall(ISDestroy(&newis));
6613   PetscCall(ISDestroy(&is));
6614   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6615   PetscFunctionReturn(PETSC_SUCCESS);
6616 }
6617 
6618 /*@
6619   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6620   of a set of rows and columns of a matrix; using local numbering of rows.
6621 
6622   Collective
6623 
6624   Input Parameters:
6625 + mat  - the matrix
6626 . is   - index set of rows to remove
6627 . diag - value put in all diagonals of eliminated rows
6628 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6629 - b    - optional vector of right hand side, that will be adjusted by provided solution
6630 
6631   Level: intermediate
6632 
6633   Notes:
6634   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6635   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6636 
6637   See `MatZeroRowsColumns()` for details on how this routine operates.
6638 
6639 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6640           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6641 @*/
6642 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6643 {
6644   PetscInt        numRows;
6645   const PetscInt *rows;
6646 
6647   PetscFunctionBegin;
6648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6649   PetscValidType(mat, 1);
6650   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6651   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6652   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6653   MatCheckPreallocated(mat, 1);
6654 
6655   PetscCall(ISGetLocalSize(is, &numRows));
6656   PetscCall(ISGetIndices(is, &rows));
6657   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6658   PetscCall(ISRestoreIndices(is, &rows));
6659   PetscFunctionReturn(PETSC_SUCCESS);
6660 }
6661 
6662 /*@C
6663   MatGetSize - Returns the numbers of rows and columns in a matrix.
6664 
6665   Not Collective
6666 
6667   Input Parameter:
6668 . mat - the matrix
6669 
6670   Output Parameters:
6671 + m - the number of global rows
6672 - n - the number of global columns
6673 
6674   Level: beginner
6675 
6676   Note:
6677   Both output parameters can be `NULL` on input.
6678 
6679 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6680 @*/
6681 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6682 {
6683   PetscFunctionBegin;
6684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6685   if (m) *m = mat->rmap->N;
6686   if (n) *n = mat->cmap->N;
6687   PetscFunctionReturn(PETSC_SUCCESS);
6688 }
6689 
6690 /*@C
6691   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6692   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6693 
6694   Not Collective
6695 
6696   Input Parameter:
6697 . mat - the matrix
6698 
6699   Output Parameters:
6700 + m - the number of local rows, use `NULL` to not obtain this value
6701 - n - the number of local columns, use `NULL` to not obtain this value
6702 
6703   Level: beginner
6704 
6705 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6706 @*/
6707 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6708 {
6709   PetscFunctionBegin;
6710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6711   if (m) PetscAssertPointer(m, 2);
6712   if (n) PetscAssertPointer(n, 3);
6713   if (m) *m = mat->rmap->n;
6714   if (n) *n = mat->cmap->n;
6715   PetscFunctionReturn(PETSC_SUCCESS);
6716 }
6717 
6718 /*@C
6719   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6720   vector one multiplies this matrix by that are owned by this processor.
6721 
6722   Not Collective, unless matrix has not been allocated, then collective
6723 
6724   Input Parameter:
6725 . mat - the matrix
6726 
6727   Output Parameters:
6728 + m - the global index of the first local column, use `NULL` to not obtain this value
6729 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6730 
6731   Level: developer
6732 
6733   Notes:
6734   Retursns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6735   Layouts](sec_matlayout) for details on matrix layouts.
6736 
6737 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6738 @*/
6739 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6740 {
6741   PetscFunctionBegin;
6742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6743   PetscValidType(mat, 1);
6744   if (m) PetscAssertPointer(m, 2);
6745   if (n) PetscAssertPointer(n, 3);
6746   MatCheckPreallocated(mat, 1);
6747   if (m) *m = mat->cmap->rstart;
6748   if (n) *n = mat->cmap->rend;
6749   PetscFunctionReturn(PETSC_SUCCESS);
6750 }
6751 
6752 /*@C
6753   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6754   this MPI process.
6755 
6756   Not Collective
6757 
6758   Input Parameter:
6759 . mat - the matrix
6760 
6761   Output Parameters:
6762 + m - the global index of the first local row, use `NULL` to not obtain this value
6763 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6764 
6765   Level: beginner
6766 
6767   Note:
6768   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6769   would contain the result of a matrix vector product with this matrix. See [Matrix
6770   Layouts](sec_matlayout) for details on matrix layouts.
6771 
6772 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6773           `PetscLayout`
6774 @*/
6775 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6776 {
6777   PetscFunctionBegin;
6778   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6779   PetscValidType(mat, 1);
6780   if (m) PetscAssertPointer(m, 2);
6781   if (n) PetscAssertPointer(n, 3);
6782   MatCheckPreallocated(mat, 1);
6783   if (m) *m = mat->rmap->rstart;
6784   if (n) *n = mat->rmap->rend;
6785   PetscFunctionReturn(PETSC_SUCCESS);
6786 }
6787 
6788 /*@C
6789   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6790   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6791 
6792   Not Collective, unless matrix has not been allocated
6793 
6794   Input Parameter:
6795 . mat - the matrix
6796 
6797   Output Parameter:
6798 . ranges - start of each processors portion plus one more than the total length at the end
6799 
6800   Level: beginner
6801 
6802   Notes:
6803   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6804   would contain the result of a matrix vector product with this matrix. See [Matrix
6805   Layouts](sec_matlayout) for details on matrix layouts.
6806 
6807 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6808 @*/
6809 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6810 {
6811   PetscFunctionBegin;
6812   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6813   PetscValidType(mat, 1);
6814   MatCheckPreallocated(mat, 1);
6815   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6816   PetscFunctionReturn(PETSC_SUCCESS);
6817 }
6818 
6819 /*@C
6820   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6821   vector one multiplies this vector by that are owned by each processor.
6822 
6823   Not Collective, unless matrix has not been allocated
6824 
6825   Input Parameter:
6826 . mat - the matrix
6827 
6828   Output Parameter:
6829 . ranges - start of each processors portion plus one more then the total length at the end
6830 
6831   Level: beginner
6832 
6833   Notes:
6834   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6835   Layouts](sec_matlayout) for details on matrix layouts.
6836 
6837 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6838 @*/
6839 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6840 {
6841   PetscFunctionBegin;
6842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6843   PetscValidType(mat, 1);
6844   MatCheckPreallocated(mat, 1);
6845   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6846   PetscFunctionReturn(PETSC_SUCCESS);
6847 }
6848 
6849 /*@C
6850   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6851 
6852   Not Collective
6853 
6854   Input Parameter:
6855 . A - matrix
6856 
6857   Output Parameters:
6858 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6859 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6860 
6861   Level: intermediate
6862 
6863   Notes:
6864   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6865   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6866   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6867   details on matrix layouts.
6868 
6869 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6870 @*/
6871 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6872 {
6873   PetscErrorCode (*f)(Mat, IS *, IS *);
6874 
6875   PetscFunctionBegin;
6876   MatCheckPreallocated(A, 1);
6877   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6878   if (f) {
6879     PetscCall((*f)(A, rows, cols));
6880   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6881     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6882     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6883   }
6884   PetscFunctionReturn(PETSC_SUCCESS);
6885 }
6886 
6887 /*@C
6888   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6889   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6890   to complete the factorization.
6891 
6892   Collective
6893 
6894   Input Parameters:
6895 + fact - the factorized matrix obtained with `MatGetFactor()`
6896 . mat  - the matrix
6897 . row  - row permutation
6898 . col  - column permutation
6899 - info - structure containing
6900 .vb
6901       levels - number of levels of fill.
6902       expected fill - as ratio of original fill.
6903       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6904                 missing diagonal entries)
6905 .ve
6906 
6907   Level: developer
6908 
6909   Notes:
6910   See [Matrix Factorization](sec_matfactor) for additional information.
6911 
6912   Most users should employ the `KSP` interface for linear solvers
6913   instead of working directly with matrix algebra routines such as this.
6914   See, e.g., `KSPCreate()`.
6915 
6916   Uses the definition of level of fill as in Y. Saad, 2003
6917 
6918   Developer Notes:
6919   The Fortran interface is not autogenerated as the
6920   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6921 
6922   References:
6923 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6924 
6925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6926           `MatGetOrdering()`, `MatFactorInfo`
6927 @*/
6928 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6929 {
6930   PetscFunctionBegin;
6931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6932   PetscValidType(mat, 2);
6933   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6934   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6935   PetscAssertPointer(info, 5);
6936   PetscAssertPointer(fact, 1);
6937   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6938   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6939   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6940   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6941   MatCheckPreallocated(mat, 2);
6942 
6943   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6944   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6945   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6946   PetscFunctionReturn(PETSC_SUCCESS);
6947 }
6948 
6949 /*@C
6950   MatICCFactorSymbolic - Performs symbolic incomplete
6951   Cholesky factorization for a symmetric matrix.  Use
6952   `MatCholeskyFactorNumeric()` to complete the factorization.
6953 
6954   Collective
6955 
6956   Input Parameters:
6957 + fact - the factorized matrix obtained with `MatGetFactor()`
6958 . mat  - the matrix to be factored
6959 . perm - row and column permutation
6960 - info - structure containing
6961 .vb
6962       levels - number of levels of fill.
6963       expected fill - as ratio of original fill.
6964 .ve
6965 
6966   Level: developer
6967 
6968   Notes:
6969   Most users should employ the `KSP` interface for linear solvers
6970   instead of working directly with matrix algebra routines such as this.
6971   See, e.g., `KSPCreate()`.
6972 
6973   This uses the definition of level of fill as in Y. Saad, 2003
6974 
6975   Developer Notes:
6976   The Fortran interface is not autogenerated as the
6977   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6978 
6979   References:
6980 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6981 
6982 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6983 @*/
6984 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6985 {
6986   PetscFunctionBegin;
6987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6988   PetscValidType(mat, 2);
6989   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6990   PetscAssertPointer(info, 4);
6991   PetscAssertPointer(fact, 1);
6992   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6993   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6994   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6995   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6996   MatCheckPreallocated(mat, 2);
6997 
6998   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6999   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7000   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7001   PetscFunctionReturn(PETSC_SUCCESS);
7002 }
7003 
7004 /*@C
7005   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7006   points to an array of valid matrices, they may be reused to store the new
7007   submatrices.
7008 
7009   Collective
7010 
7011   Input Parameters:
7012 + mat   - the matrix
7013 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7014 . irow  - index set of rows to extract
7015 . icol  - index set of columns to extract
7016 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7017 
7018   Output Parameter:
7019 . submat - the array of submatrices
7020 
7021   Level: advanced
7022 
7023   Notes:
7024   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7025   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7026   to extract a parallel submatrix.
7027 
7028   Some matrix types place restrictions on the row and column
7029   indices, such as that they be sorted or that they be equal to each other.
7030 
7031   The index sets may not have duplicate entries.
7032 
7033   When extracting submatrices from a parallel matrix, each processor can
7034   form a different submatrix by setting the rows and columns of its
7035   individual index sets according to the local submatrix desired.
7036 
7037   When finished using the submatrices, the user should destroy
7038   them with `MatDestroySubMatrices()`.
7039 
7040   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7041   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7042 
7043   This routine creates the matrices in submat; you should NOT create them before
7044   calling it. It also allocates the array of matrix pointers submat.
7045 
7046   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7047   request one row/column in a block, they must request all rows/columns that are in
7048   that block. For example, if the block size is 2 you cannot request just row 0 and
7049   column 0.
7050 
7051   Fortran Notes:
7052   The Fortran interface is slightly different from that given below; it
7053   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7054 
7055 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7056 @*/
7057 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7058 {
7059   PetscInt  i;
7060   PetscBool eq;
7061 
7062   PetscFunctionBegin;
7063   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7064   PetscValidType(mat, 1);
7065   if (n) {
7066     PetscAssertPointer(irow, 3);
7067     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7068     PetscAssertPointer(icol, 4);
7069     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7070   }
7071   PetscAssertPointer(submat, 6);
7072   if (n && scall == MAT_REUSE_MATRIX) {
7073     PetscAssertPointer(*submat, 6);
7074     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7075   }
7076   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7077   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7078   MatCheckPreallocated(mat, 1);
7079   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7080   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7081   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7082   for (i = 0; i < n; i++) {
7083     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7084     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7085     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7086 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7087     if (mat->boundtocpu && mat->bindingpropagates) {
7088       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7089       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7090     }
7091 #endif
7092   }
7093   PetscFunctionReturn(PETSC_SUCCESS);
7094 }
7095 
7096 /*@C
7097   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7098 
7099   Collective
7100 
7101   Input Parameters:
7102 + mat   - the matrix
7103 . n     - the number of submatrixes to be extracted
7104 . irow  - index set of rows to extract
7105 . icol  - index set of columns to extract
7106 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7107 
7108   Output Parameter:
7109 . submat - the array of submatrices
7110 
7111   Level: advanced
7112 
7113   Note:
7114   This is used by `PCGASM`
7115 
7116 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7117 @*/
7118 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7119 {
7120   PetscInt  i;
7121   PetscBool eq;
7122 
7123   PetscFunctionBegin;
7124   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7125   PetscValidType(mat, 1);
7126   if (n) {
7127     PetscAssertPointer(irow, 3);
7128     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7129     PetscAssertPointer(icol, 4);
7130     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7131   }
7132   PetscAssertPointer(submat, 6);
7133   if (n && scall == MAT_REUSE_MATRIX) {
7134     PetscAssertPointer(*submat, 6);
7135     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7136   }
7137   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7138   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7139   MatCheckPreallocated(mat, 1);
7140 
7141   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7142   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7143   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7144   for (i = 0; i < n; i++) {
7145     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7146     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7147   }
7148   PetscFunctionReturn(PETSC_SUCCESS);
7149 }
7150 
7151 /*@C
7152   MatDestroyMatrices - Destroys an array of matrices.
7153 
7154   Collective
7155 
7156   Input Parameters:
7157 + n   - the number of local matrices
7158 - mat - the matrices (this is a pointer to the array of matrices)
7159 
7160   Level: advanced
7161 
7162   Note:
7163   Frees not only the matrices, but also the array that contains the matrices
7164 
7165   Fortran Notes:
7166   This does not free the array.
7167 
7168 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7169 @*/
7170 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7171 {
7172   PetscInt i;
7173 
7174   PetscFunctionBegin;
7175   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7176   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7177   PetscAssertPointer(mat, 2);
7178 
7179   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7180 
7181   /* memory is allocated even if n = 0 */
7182   PetscCall(PetscFree(*mat));
7183   PetscFunctionReturn(PETSC_SUCCESS);
7184 }
7185 
7186 /*@C
7187   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7188 
7189   Collective
7190 
7191   Input Parameters:
7192 + n   - the number of local matrices
7193 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7194                        sequence of `MatCreateSubMatrices()`)
7195 
7196   Level: advanced
7197 
7198   Note:
7199   Frees not only the matrices, but also the array that contains the matrices
7200 
7201   Fortran Notes:
7202   This does not free the array.
7203 
7204 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7205 @*/
7206 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7207 {
7208   Mat mat0;
7209 
7210   PetscFunctionBegin;
7211   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7212   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7213   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7214   PetscAssertPointer(mat, 2);
7215 
7216   mat0 = (*mat)[0];
7217   if (mat0 && mat0->ops->destroysubmatrices) {
7218     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7219   } else {
7220     PetscCall(MatDestroyMatrices(n, mat));
7221   }
7222   PetscFunctionReturn(PETSC_SUCCESS);
7223 }
7224 
7225 /*@C
7226   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7227 
7228   Collective
7229 
7230   Input Parameter:
7231 . mat - the matrix
7232 
7233   Output Parameter:
7234 . matstruct - the sequential matrix with the nonzero structure of mat
7235 
7236   Level: developer
7237 
7238 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7239 @*/
7240 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7241 {
7242   PetscFunctionBegin;
7243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7244   PetscAssertPointer(matstruct, 2);
7245 
7246   PetscValidType(mat, 1);
7247   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7248   MatCheckPreallocated(mat, 1);
7249 
7250   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7251   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7252   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7253   PetscFunctionReturn(PETSC_SUCCESS);
7254 }
7255 
7256 /*@C
7257   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7258 
7259   Collective
7260 
7261   Input Parameter:
7262 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7263                        sequence of `MatGetSeqNonzeroStructure()`)
7264 
7265   Level: advanced
7266 
7267   Note:
7268   Frees not only the matrices, but also the array that contains the matrices
7269 
7270 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7271 @*/
7272 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7273 {
7274   PetscFunctionBegin;
7275   PetscAssertPointer(mat, 1);
7276   PetscCall(MatDestroy(mat));
7277   PetscFunctionReturn(PETSC_SUCCESS);
7278 }
7279 
7280 /*@
7281   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7282   replaces the index sets by larger ones that represent submatrices with
7283   additional overlap.
7284 
7285   Collective
7286 
7287   Input Parameters:
7288 + mat - the matrix
7289 . n   - the number of index sets
7290 . is  - the array of index sets (these index sets will changed during the call)
7291 - ov  - the additional overlap requested
7292 
7293   Options Database Key:
7294 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7295 
7296   Level: developer
7297 
7298   Note:
7299   The computed overlap preserves the matrix block sizes when the blocks are square.
7300   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7301   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7302 
7303 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7304 @*/
7305 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7306 {
7307   PetscInt i, bs, cbs;
7308 
7309   PetscFunctionBegin;
7310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7311   PetscValidType(mat, 1);
7312   PetscValidLogicalCollectiveInt(mat, n, 2);
7313   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7314   if (n) {
7315     PetscAssertPointer(is, 3);
7316     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7317   }
7318   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7319   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7320   MatCheckPreallocated(mat, 1);
7321 
7322   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7323   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7324   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7325   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7326   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7327   if (bs == cbs) {
7328     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7329   }
7330   PetscFunctionReturn(PETSC_SUCCESS);
7331 }
7332 
7333 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7334 
7335 /*@
7336   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7337   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7338   additional overlap.
7339 
7340   Collective
7341 
7342   Input Parameters:
7343 + mat - the matrix
7344 . n   - the number of index sets
7345 . is  - the array of index sets (these index sets will changed during the call)
7346 - ov  - the additional overlap requested
7347 
7348   `   Options Database Key:
7349 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7350 
7351   Level: developer
7352 
7353 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7354 @*/
7355 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7356 {
7357   PetscInt i;
7358 
7359   PetscFunctionBegin;
7360   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7361   PetscValidType(mat, 1);
7362   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7363   if (n) {
7364     PetscAssertPointer(is, 3);
7365     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7366   }
7367   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7368   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7369   MatCheckPreallocated(mat, 1);
7370   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7371   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7372   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7373   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7374   PetscFunctionReturn(PETSC_SUCCESS);
7375 }
7376 
7377 /*@
7378   MatGetBlockSize - Returns the matrix block size.
7379 
7380   Not Collective
7381 
7382   Input Parameter:
7383 . mat - the matrix
7384 
7385   Output Parameter:
7386 . bs - block size
7387 
7388   Level: intermediate
7389 
7390   Notes:
7391   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7392 
7393   If the block size has not been set yet this routine returns 1.
7394 
7395 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7396 @*/
7397 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7398 {
7399   PetscFunctionBegin;
7400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7401   PetscAssertPointer(bs, 2);
7402   *bs = PetscAbs(mat->rmap->bs);
7403   PetscFunctionReturn(PETSC_SUCCESS);
7404 }
7405 
7406 /*@
7407   MatGetBlockSizes - Returns the matrix block row and column sizes.
7408 
7409   Not Collective
7410 
7411   Input Parameter:
7412 . mat - the matrix
7413 
7414   Output Parameters:
7415 + rbs - row block size
7416 - cbs - column block size
7417 
7418   Level: intermediate
7419 
7420   Notes:
7421   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7422   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7423 
7424   If a block size has not been set yet this routine returns 1.
7425 
7426 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7427 @*/
7428 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7429 {
7430   PetscFunctionBegin;
7431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7432   if (rbs) PetscAssertPointer(rbs, 2);
7433   if (cbs) PetscAssertPointer(cbs, 3);
7434   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7435   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7436   PetscFunctionReturn(PETSC_SUCCESS);
7437 }
7438 
7439 /*@
7440   MatSetBlockSize - Sets the matrix block size.
7441 
7442   Logically Collective
7443 
7444   Input Parameters:
7445 + mat - the matrix
7446 - bs  - block size
7447 
7448   Level: intermediate
7449 
7450   Notes:
7451   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7452   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7453 
7454   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7455   is compatible with the matrix local sizes.
7456 
7457 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7458 @*/
7459 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7460 {
7461   PetscFunctionBegin;
7462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7463   PetscValidLogicalCollectiveInt(mat, bs, 2);
7464   PetscCall(MatSetBlockSizes(mat, bs, bs));
7465   PetscFunctionReturn(PETSC_SUCCESS);
7466 }
7467 
7468 typedef struct {
7469   PetscInt         n;
7470   IS              *is;
7471   Mat             *mat;
7472   PetscObjectState nonzerostate;
7473   Mat              C;
7474 } EnvelopeData;
7475 
7476 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7477 {
7478   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7479   PetscCall(PetscFree(edata->is));
7480   PetscCall(PetscFree(edata));
7481   return PETSC_SUCCESS;
7482 }
7483 
7484 /*@
7485   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7486   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7487 
7488   Collective
7489 
7490   Input Parameter:
7491 . mat - the matrix
7492 
7493   Level: intermediate
7494 
7495   Notes:
7496   There can be zeros within the blocks
7497 
7498   The blocks can overlap between processes, including laying on more than two processes
7499 
7500 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7501 @*/
7502 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7503 {
7504   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7505   PetscInt          *diag, *odiag, sc;
7506   VecScatter         scatter;
7507   PetscScalar       *seqv;
7508   const PetscScalar *parv;
7509   const PetscInt    *ia, *ja;
7510   PetscBool          set, flag, done;
7511   Mat                AA = mat, A;
7512   MPI_Comm           comm;
7513   PetscMPIInt        rank, size, tag;
7514   MPI_Status         status;
7515   PetscContainer     container;
7516   EnvelopeData      *edata;
7517   Vec                seq, par;
7518   IS                 isglobal;
7519 
7520   PetscFunctionBegin;
7521   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7522   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7523   if (!set || !flag) {
7524     /* TODO: only needs nonzero structure of transpose */
7525     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7526     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7527   }
7528   PetscCall(MatAIJGetLocalMat(AA, &A));
7529   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7530   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7531 
7532   PetscCall(MatGetLocalSize(mat, &n, NULL));
7533   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7534   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7535   PetscCallMPI(MPI_Comm_size(comm, &size));
7536   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7537 
7538   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7539 
7540   if (rank > 0) {
7541     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7542     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7543   }
7544   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7545   for (i = 0; i < n; i++) {
7546     env = PetscMax(env, ja[ia[i + 1] - 1]);
7547     II  = rstart + i;
7548     if (env == II) {
7549       starts[lblocks]  = tbs;
7550       sizes[lblocks++] = 1 + II - tbs;
7551       tbs              = 1 + II;
7552     }
7553   }
7554   if (rank < size - 1) {
7555     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7556     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7557   }
7558 
7559   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7560   if (!set || !flag) PetscCall(MatDestroy(&AA));
7561   PetscCall(MatDestroy(&A));
7562 
7563   PetscCall(PetscNew(&edata));
7564   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7565   edata->n = lblocks;
7566   /* create IS needed for extracting blocks from the original matrix */
7567   PetscCall(PetscMalloc1(lblocks, &edata->is));
7568   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7569 
7570   /* Create the resulting inverse matrix structure with preallocation information */
7571   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7572   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7573   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7574   PetscCall(MatSetType(edata->C, MATAIJ));
7575 
7576   /* Communicate the start and end of each row, from each block to the correct rank */
7577   /* TODO: Use PetscSF instead of VecScatter */
7578   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7579   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7580   PetscCall(VecGetArrayWrite(seq, &seqv));
7581   for (PetscInt i = 0; i < lblocks; i++) {
7582     for (PetscInt j = 0; j < sizes[i]; j++) {
7583       seqv[cnt]     = starts[i];
7584       seqv[cnt + 1] = starts[i] + sizes[i];
7585       cnt += 2;
7586     }
7587   }
7588   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7589   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7590   sc -= cnt;
7591   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7592   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7593   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7594   PetscCall(ISDestroy(&isglobal));
7595   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7596   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7597   PetscCall(VecScatterDestroy(&scatter));
7598   PetscCall(VecDestroy(&seq));
7599   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7600   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7601   PetscCall(VecGetArrayRead(par, &parv));
7602   cnt = 0;
7603   PetscCall(MatGetSize(mat, NULL, &n));
7604   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7605     PetscInt start, end, d = 0, od = 0;
7606 
7607     start = (PetscInt)PetscRealPart(parv[cnt]);
7608     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7609     cnt += 2;
7610 
7611     if (start < cstart) {
7612       od += cstart - start + n - cend;
7613       d += cend - cstart;
7614     } else if (start < cend) {
7615       od += n - cend;
7616       d += cend - start;
7617     } else od += n - start;
7618     if (end <= cstart) {
7619       od -= cstart - end + n - cend;
7620       d -= cend - cstart;
7621     } else if (end < cend) {
7622       od -= n - cend;
7623       d -= cend - end;
7624     } else od -= n - end;
7625 
7626     odiag[i] = od;
7627     diag[i]  = d;
7628   }
7629   PetscCall(VecRestoreArrayRead(par, &parv));
7630   PetscCall(VecDestroy(&par));
7631   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7632   PetscCall(PetscFree2(diag, odiag));
7633   PetscCall(PetscFree2(sizes, starts));
7634 
7635   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7636   PetscCall(PetscContainerSetPointer(container, edata));
7637   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7638   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7639   PetscCall(PetscObjectDereference((PetscObject)container));
7640   PetscFunctionReturn(PETSC_SUCCESS);
7641 }
7642 
7643 /*@
7644   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7645 
7646   Collective
7647 
7648   Input Parameters:
7649 + A     - the matrix
7650 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7651 
7652   Output Parameter:
7653 . C - matrix with inverted block diagonal of `A`
7654 
7655   Level: advanced
7656 
7657   Note:
7658   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7659 
7660 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7661 @*/
7662 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7663 {
7664   PetscContainer   container;
7665   EnvelopeData    *edata;
7666   PetscObjectState nonzerostate;
7667 
7668   PetscFunctionBegin;
7669   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7670   if (!container) {
7671     PetscCall(MatComputeVariableBlockEnvelope(A));
7672     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7673   }
7674   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7675   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7676   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7677   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7678 
7679   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7680   *C = edata->C;
7681 
7682   for (PetscInt i = 0; i < edata->n; i++) {
7683     Mat          D;
7684     PetscScalar *dvalues;
7685 
7686     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7687     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7688     PetscCall(MatSeqDenseInvert(D));
7689     PetscCall(MatDenseGetArray(D, &dvalues));
7690     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7691     PetscCall(MatDestroy(&D));
7692   }
7693   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7694   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7695   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7696   PetscFunctionReturn(PETSC_SUCCESS);
7697 }
7698 
7699 /*@
7700   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7701 
7702   Logically Collective
7703 
7704   Input Parameters:
7705 + mat     - the matrix
7706 . nblocks - the number of blocks on this process, each block can only exist on a single process
7707 - bsizes  - the block sizes
7708 
7709   Level: intermediate
7710 
7711   Notes:
7712   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7713 
7714   Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes.
7715 
7716 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7717           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7718 @*/
7719 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7720 {
7721   PetscInt i, ncnt = 0, nlocal;
7722 
7723   PetscFunctionBegin;
7724   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7725   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7726   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7727   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7728   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);
7729   PetscCall(PetscFree(mat->bsizes));
7730   mat->nblocks = nblocks;
7731   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7732   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7733   PetscFunctionReturn(PETSC_SUCCESS);
7734 }
7735 
7736 /*@C
7737   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7738 
7739   Logically Collective; No Fortran Support
7740 
7741   Input Parameter:
7742 . mat - the matrix
7743 
7744   Output Parameters:
7745 + nblocks - the number of blocks on this process
7746 - bsizes  - the block sizes
7747 
7748   Level: intermediate
7749 
7750 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7751 @*/
7752 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7753 {
7754   PetscFunctionBegin;
7755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7756   *nblocks = mat->nblocks;
7757   *bsizes  = mat->bsizes;
7758   PetscFunctionReturn(PETSC_SUCCESS);
7759 }
7760 
7761 /*@
7762   MatSetBlockSizes - Sets the matrix block row and column sizes.
7763 
7764   Logically Collective
7765 
7766   Input Parameters:
7767 + mat - the matrix
7768 . rbs - row block size
7769 - cbs - column block size
7770 
7771   Level: intermediate
7772 
7773   Notes:
7774   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7775   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7776   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7777 
7778   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7779   are compatible with the matrix local sizes.
7780 
7781   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7782 
7783 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7784 @*/
7785 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7786 {
7787   PetscFunctionBegin;
7788   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7789   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7790   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7791   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7792   if (mat->rmap->refcnt) {
7793     ISLocalToGlobalMapping l2g  = NULL;
7794     PetscLayout            nmap = NULL;
7795 
7796     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7797     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7798     PetscCall(PetscLayoutDestroy(&mat->rmap));
7799     mat->rmap          = nmap;
7800     mat->rmap->mapping = l2g;
7801   }
7802   if (mat->cmap->refcnt) {
7803     ISLocalToGlobalMapping l2g  = NULL;
7804     PetscLayout            nmap = NULL;
7805 
7806     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7807     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7808     PetscCall(PetscLayoutDestroy(&mat->cmap));
7809     mat->cmap          = nmap;
7810     mat->cmap->mapping = l2g;
7811   }
7812   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7813   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7814   PetscFunctionReturn(PETSC_SUCCESS);
7815 }
7816 
7817 /*@
7818   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7819 
7820   Logically Collective
7821 
7822   Input Parameters:
7823 + mat     - the matrix
7824 . fromRow - matrix from which to copy row block size
7825 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7826 
7827   Level: developer
7828 
7829 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7830 @*/
7831 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7832 {
7833   PetscFunctionBegin;
7834   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7835   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7836   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7837   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7838   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7839   PetscFunctionReturn(PETSC_SUCCESS);
7840 }
7841 
7842 /*@
7843   MatResidual - Default routine to calculate the residual r = b - Ax
7844 
7845   Collective
7846 
7847   Input Parameters:
7848 + mat - the matrix
7849 . b   - the right-hand-side
7850 - x   - the approximate solution
7851 
7852   Output Parameter:
7853 . r - location to store the residual
7854 
7855   Level: developer
7856 
7857 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7858 @*/
7859 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7860 {
7861   PetscFunctionBegin;
7862   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7863   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7864   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7865   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7866   PetscValidType(mat, 1);
7867   MatCheckPreallocated(mat, 1);
7868   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7869   if (!mat->ops->residual) {
7870     PetscCall(MatMult(mat, x, r));
7871     PetscCall(VecAYPX(r, -1.0, b));
7872   } else {
7873     PetscUseTypeMethod(mat, residual, b, x, r);
7874   }
7875   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7876   PetscFunctionReturn(PETSC_SUCCESS);
7877 }
7878 
7879 /*MC
7880     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7881 
7882     Synopsis:
7883     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7884 
7885     Not Collective
7886 
7887     Input Parameters:
7888 +   A - the matrix
7889 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7890 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7891 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7892                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7893                  always used.
7894 
7895     Output Parameters:
7896 +   n - number of local rows in the (possibly compressed) matrix
7897 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7898 .   ja - the column indices
7899 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7900            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7901 
7902     Level: developer
7903 
7904     Note:
7905     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7906 
7907 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7908 M*/
7909 
7910 /*MC
7911     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7912 
7913     Synopsis:
7914     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7915 
7916     Not Collective
7917 
7918     Input Parameters:
7919 +   A - the  matrix
7920 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7921 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7922     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7923                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7924                  always used.
7925 .   n - number of local rows in the (possibly compressed) matrix
7926 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7927 .   ja - the column indices
7928 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7929            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7930 
7931     Level: developer
7932 
7933 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7934 M*/
7935 
7936 /*@C
7937   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7938 
7939   Collective
7940 
7941   Input Parameters:
7942 + mat             - the matrix
7943 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7944 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7945 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7946                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7947                  always used.
7948 
7949   Output Parameters:
7950 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7951 . 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
7952 . ja   - the column indices, use `NULL` if not needed
7953 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7954            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7955 
7956   Level: developer
7957 
7958   Notes:
7959   You CANNOT change any of the ia[] or ja[] values.
7960 
7961   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7962 
7963   Fortran Notes:
7964   Use
7965 .vb
7966     PetscInt, pointer :: ia(:),ja(:)
7967     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7968     ! Access the ith and jth entries via ia(i) and ja(j)
7969 .ve
7970   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7971 
7972 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7973 @*/
7974 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7975 {
7976   PetscFunctionBegin;
7977   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7978   PetscValidType(mat, 1);
7979   if (n) PetscAssertPointer(n, 5);
7980   if (ia) PetscAssertPointer(ia, 6);
7981   if (ja) PetscAssertPointer(ja, 7);
7982   if (done) PetscAssertPointer(done, 8);
7983   MatCheckPreallocated(mat, 1);
7984   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7985   else {
7986     if (done) *done = PETSC_TRUE;
7987     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7988     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7989     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7990   }
7991   PetscFunctionReturn(PETSC_SUCCESS);
7992 }
7993 
7994 /*@C
7995   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7996 
7997   Collective
7998 
7999   Input Parameters:
8000 + mat             - the matrix
8001 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8002 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8003                 symmetrized
8004 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8005                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8006                  always used.
8007 . n               - number of columns in the (possibly compressed) matrix
8008 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8009 - ja              - the row indices
8010 
8011   Output Parameter:
8012 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8013 
8014   Level: developer
8015 
8016 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8017 @*/
8018 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8019 {
8020   PetscFunctionBegin;
8021   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8022   PetscValidType(mat, 1);
8023   PetscAssertPointer(n, 5);
8024   if (ia) PetscAssertPointer(ia, 6);
8025   if (ja) PetscAssertPointer(ja, 7);
8026   PetscAssertPointer(done, 8);
8027   MatCheckPreallocated(mat, 1);
8028   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8029   else {
8030     *done = PETSC_TRUE;
8031     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8032   }
8033   PetscFunctionReturn(PETSC_SUCCESS);
8034 }
8035 
8036 /*@C
8037   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8038 
8039   Collective
8040 
8041   Input Parameters:
8042 + mat             - the matrix
8043 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8044 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8045 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8046                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8047                  always used.
8048 . n               - size of (possibly compressed) matrix
8049 . ia              - the row pointers
8050 - ja              - the column indices
8051 
8052   Output Parameter:
8053 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8054 
8055   Level: developer
8056 
8057   Note:
8058   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8059   us of the array after it has been restored. If you pass `NULL`, it will
8060   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8061 
8062   Fortran Notes:
8063   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8064 
8065 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8066 @*/
8067 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8068 {
8069   PetscFunctionBegin;
8070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8071   PetscValidType(mat, 1);
8072   if (ia) PetscAssertPointer(ia, 6);
8073   if (ja) PetscAssertPointer(ja, 7);
8074   if (done) PetscAssertPointer(done, 8);
8075   MatCheckPreallocated(mat, 1);
8076 
8077   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8078   else {
8079     if (done) *done = PETSC_TRUE;
8080     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8081     if (n) *n = 0;
8082     if (ia) *ia = NULL;
8083     if (ja) *ja = NULL;
8084   }
8085   PetscFunctionReturn(PETSC_SUCCESS);
8086 }
8087 
8088 /*@C
8089   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8090 
8091   Collective
8092 
8093   Input Parameters:
8094 + mat             - the matrix
8095 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8096 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8097 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8098                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8099                  always used.
8100 
8101   Output Parameters:
8102 + n    - size of (possibly compressed) matrix
8103 . ia   - the column pointers
8104 . ja   - the row indices
8105 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8106 
8107   Level: developer
8108 
8109 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8110 @*/
8111 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8112 {
8113   PetscFunctionBegin;
8114   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8115   PetscValidType(mat, 1);
8116   if (ia) PetscAssertPointer(ia, 6);
8117   if (ja) PetscAssertPointer(ja, 7);
8118   PetscAssertPointer(done, 8);
8119   MatCheckPreallocated(mat, 1);
8120 
8121   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8122   else {
8123     *done = PETSC_TRUE;
8124     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8125     if (n) *n = 0;
8126     if (ia) *ia = NULL;
8127     if (ja) *ja = NULL;
8128   }
8129   PetscFunctionReturn(PETSC_SUCCESS);
8130 }
8131 
8132 /*@C
8133   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8134   `MatGetColumnIJ()`.
8135 
8136   Collective
8137 
8138   Input Parameters:
8139 + mat        - the matrix
8140 . ncolors    - maximum color value
8141 . n          - number of entries in colorarray
8142 - colorarray - array indicating color for each column
8143 
8144   Output Parameter:
8145 . iscoloring - coloring generated using colorarray information
8146 
8147   Level: developer
8148 
8149 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8150 @*/
8151 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8152 {
8153   PetscFunctionBegin;
8154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8155   PetscValidType(mat, 1);
8156   PetscAssertPointer(colorarray, 4);
8157   PetscAssertPointer(iscoloring, 5);
8158   MatCheckPreallocated(mat, 1);
8159 
8160   if (!mat->ops->coloringpatch) {
8161     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8162   } else {
8163     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8164   }
8165   PetscFunctionReturn(PETSC_SUCCESS);
8166 }
8167 
8168 /*@
8169   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8170 
8171   Logically Collective
8172 
8173   Input Parameter:
8174 . mat - the factored matrix to be reset
8175 
8176   Level: developer
8177 
8178   Notes:
8179   This routine should be used only with factored matrices formed by in-place
8180   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8181   format).  This option can save memory, for example, when solving nonlinear
8182   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8183   ILU(0) preconditioner.
8184 
8185   One can specify in-place ILU(0) factorization by calling
8186 .vb
8187      PCType(pc,PCILU);
8188      PCFactorSeUseInPlace(pc);
8189 .ve
8190   or by using the options -pc_type ilu -pc_factor_in_place
8191 
8192   In-place factorization ILU(0) can also be used as a local
8193   solver for the blocks within the block Jacobi or additive Schwarz
8194   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8195   for details on setting local solver options.
8196 
8197   Most users should employ the `KSP` interface for linear solvers
8198   instead of working directly with matrix algebra routines such as this.
8199   See, e.g., `KSPCreate()`.
8200 
8201 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8202 @*/
8203 PetscErrorCode MatSetUnfactored(Mat mat)
8204 {
8205   PetscFunctionBegin;
8206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8207   PetscValidType(mat, 1);
8208   MatCheckPreallocated(mat, 1);
8209   mat->factortype = MAT_FACTOR_NONE;
8210   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8211   PetscUseTypeMethod(mat, setunfactored);
8212   PetscFunctionReturn(PETSC_SUCCESS);
8213 }
8214 
8215 /*MC
8216     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8217 
8218     Synopsis:
8219     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8220 
8221     Not Collective
8222 
8223     Input Parameter:
8224 .   x - matrix
8225 
8226     Output Parameters:
8227 +   xx_v - the Fortran pointer to the array
8228 -   ierr - error code
8229 
8230     Example of Usage:
8231 .vb
8232       PetscScalar, pointer xx_v(:,:)
8233       ....
8234       call MatDenseGetArrayF90(x,xx_v,ierr)
8235       a = xx_v(3)
8236       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8237 .ve
8238 
8239     Level: advanced
8240 
8241 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8242 M*/
8243 
8244 /*MC
8245     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8246     accessed with `MatDenseGetArrayF90()`.
8247 
8248     Synopsis:
8249     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8250 
8251     Not Collective
8252 
8253     Input Parameters:
8254 +   x - matrix
8255 -   xx_v - the Fortran90 pointer to the array
8256 
8257     Output Parameter:
8258 .   ierr - error code
8259 
8260     Example of Usage:
8261 .vb
8262        PetscScalar, pointer xx_v(:,:)
8263        ....
8264        call MatDenseGetArrayF90(x,xx_v,ierr)
8265        a = xx_v(3)
8266        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8267 .ve
8268 
8269     Level: advanced
8270 
8271 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8272 M*/
8273 
8274 /*MC
8275     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8276 
8277     Synopsis:
8278     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8279 
8280     Not Collective
8281 
8282     Input Parameter:
8283 .   x - matrix
8284 
8285     Output Parameters:
8286 +   xx_v - the Fortran pointer to the array
8287 -   ierr - error code
8288 
8289     Example of Usage:
8290 .vb
8291       PetscScalar, pointer xx_v(:)
8292       ....
8293       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8294       a = xx_v(3)
8295       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8296 .ve
8297 
8298     Level: advanced
8299 
8300 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8301 M*/
8302 
8303 /*MC
8304     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8305     accessed with `MatSeqAIJGetArrayF90()`.
8306 
8307     Synopsis:
8308     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8309 
8310     Not Collective
8311 
8312     Input Parameters:
8313 +   x - matrix
8314 -   xx_v - the Fortran90 pointer to the array
8315 
8316     Output Parameter:
8317 .   ierr - error code
8318 
8319     Example of Usage:
8320 .vb
8321        PetscScalar, pointer xx_v(:)
8322        ....
8323        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8324        a = xx_v(3)
8325        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8326 .ve
8327 
8328     Level: advanced
8329 
8330 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8331 M*/
8332 
8333 /*@
8334   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8335   as the original matrix.
8336 
8337   Collective
8338 
8339   Input Parameters:
8340 + mat   - the original matrix
8341 . isrow - parallel `IS` containing the rows this processor should obtain
8342 . 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.
8343 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8344 
8345   Output Parameter:
8346 . newmat - the new submatrix, of the same type as the original matrix
8347 
8348   Level: advanced
8349 
8350   Notes:
8351   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8352 
8353   Some matrix types place restrictions on the row and column indices, such
8354   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;
8355   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8356 
8357   The index sets may not have duplicate entries.
8358 
8359   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8360   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8361   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8362   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8363   you are finished using it.
8364 
8365   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8366   the input matrix.
8367 
8368   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8369 
8370   Example usage:
8371   Consider the following 8x8 matrix with 34 non-zero values, that is
8372   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8373   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8374   as follows
8375 .vb
8376             1  2  0  |  0  3  0  |  0  4
8377     Proc0   0  5  6  |  7  0  0  |  8  0
8378             9  0 10  | 11  0  0  | 12  0
8379     -------------------------------------
8380            13  0 14  | 15 16 17  |  0  0
8381     Proc1   0 18  0  | 19 20 21  |  0  0
8382             0  0  0  | 22 23  0  | 24  0
8383     -------------------------------------
8384     Proc2  25 26 27  |  0  0 28  | 29  0
8385            30  0  0  | 31 32 33  |  0 34
8386 .ve
8387 
8388   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8389 
8390 .vb
8391             2  0  |  0  3  0  |  0
8392     Proc0   5  6  |  7  0  0  |  8
8393     -------------------------------
8394     Proc1  18  0  | 19 20 21  |  0
8395     -------------------------------
8396     Proc2  26 27  |  0  0 28  | 29
8397             0  0  | 31 32 33  |  0
8398 .ve
8399 
8400 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8401 @*/
8402 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8403 {
8404   PetscMPIInt size;
8405   Mat        *local;
8406   IS          iscoltmp;
8407   PetscBool   flg;
8408 
8409   PetscFunctionBegin;
8410   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8411   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8412   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8413   PetscAssertPointer(newmat, 5);
8414   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8415   PetscValidType(mat, 1);
8416   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8417   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8418 
8419   MatCheckPreallocated(mat, 1);
8420   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8421 
8422   if (!iscol || isrow == iscol) {
8423     PetscBool   stride;
8424     PetscMPIInt grabentirematrix = 0, grab;
8425     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8426     if (stride) {
8427       PetscInt first, step, n, rstart, rend;
8428       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8429       if (step == 1) {
8430         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8431         if (rstart == first) {
8432           PetscCall(ISGetLocalSize(isrow, &n));
8433           if (n == rend - rstart) grabentirematrix = 1;
8434         }
8435       }
8436     }
8437     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8438     if (grab) {
8439       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8440       if (cll == MAT_INITIAL_MATRIX) {
8441         *newmat = mat;
8442         PetscCall(PetscObjectReference((PetscObject)mat));
8443       }
8444       PetscFunctionReturn(PETSC_SUCCESS);
8445     }
8446   }
8447 
8448   if (!iscol) {
8449     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8450   } else {
8451     iscoltmp = iscol;
8452   }
8453 
8454   /* if original matrix is on just one processor then use submatrix generated */
8455   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8456     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8457     goto setproperties;
8458   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8459     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8460     *newmat = *local;
8461     PetscCall(PetscFree(local));
8462     goto setproperties;
8463   } else if (!mat->ops->createsubmatrix) {
8464     /* Create a new matrix type that implements the operation using the full matrix */
8465     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8466     switch (cll) {
8467     case MAT_INITIAL_MATRIX:
8468       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8469       break;
8470     case MAT_REUSE_MATRIX:
8471       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8472       break;
8473     default:
8474       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8475     }
8476     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8477     goto setproperties;
8478   }
8479 
8480   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8481   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8482   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8483 
8484 setproperties:
8485   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8486   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8487   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8488   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8489   PetscFunctionReturn(PETSC_SUCCESS);
8490 }
8491 
8492 /*@
8493   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8494 
8495   Not Collective
8496 
8497   Input Parameters:
8498 + A - the matrix we wish to propagate options from
8499 - B - the matrix we wish to propagate options to
8500 
8501   Level: beginner
8502 
8503   Note:
8504   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8505 
8506 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8507 @*/
8508 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8509 {
8510   PetscFunctionBegin;
8511   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8512   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8513   B->symmetry_eternal            = A->symmetry_eternal;
8514   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8515   B->symmetric                   = A->symmetric;
8516   B->structurally_symmetric      = A->structurally_symmetric;
8517   B->spd                         = A->spd;
8518   B->hermitian                   = A->hermitian;
8519   PetscFunctionReturn(PETSC_SUCCESS);
8520 }
8521 
8522 /*@
8523   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8524   used during the assembly process to store values that belong to
8525   other processors.
8526 
8527   Not Collective
8528 
8529   Input Parameters:
8530 + mat   - the matrix
8531 . size  - the initial size of the stash.
8532 - bsize - the initial size of the block-stash(if used).
8533 
8534   Options Database Keys:
8535 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8536 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8537 
8538   Level: intermediate
8539 
8540   Notes:
8541   The block-stash is used for values set with `MatSetValuesBlocked()` while
8542   the stash is used for values set with `MatSetValues()`
8543 
8544   Run with the option -info and look for output of the form
8545   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8546   to determine the appropriate value, MM, to use for size and
8547   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8548   to determine the value, BMM to use for bsize
8549 
8550 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8551 @*/
8552 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8553 {
8554   PetscFunctionBegin;
8555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8556   PetscValidType(mat, 1);
8557   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8558   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8559   PetscFunctionReturn(PETSC_SUCCESS);
8560 }
8561 
8562 /*@
8563   MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8564   the matrix
8565 
8566   Neighbor-wise Collective
8567 
8568   Input Parameters:
8569 + A - the matrix
8570 . x - the vector to be multiplied by the interpolation operator
8571 - y - the vector to be added to the result
8572 
8573   Output Parameter:
8574 . w - the resulting vector
8575 
8576   Level: intermediate
8577 
8578   Notes:
8579   `w` may be the same vector as `y`.
8580 
8581   This allows one to use either the restriction or interpolation (its transpose)
8582   matrix to do the interpolation
8583 
8584 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8585 @*/
8586 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8587 {
8588   PetscInt M, N, Ny;
8589 
8590   PetscFunctionBegin;
8591   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8592   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8593   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8594   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8595   PetscCall(MatGetSize(A, &M, &N));
8596   PetscCall(VecGetSize(y, &Ny));
8597   if (M == Ny) {
8598     PetscCall(MatMultAdd(A, x, y, w));
8599   } else {
8600     PetscCall(MatMultTransposeAdd(A, x, y, w));
8601   }
8602   PetscFunctionReturn(PETSC_SUCCESS);
8603 }
8604 
8605 /*@
8606   MatInterpolate - y = A*x or A'*x depending on the shape of
8607   the matrix
8608 
8609   Neighbor-wise Collective
8610 
8611   Input Parameters:
8612 + A - the matrix
8613 - x - the vector to be interpolated
8614 
8615   Output Parameter:
8616 . y - the resulting vector
8617 
8618   Level: intermediate
8619 
8620   Note:
8621   This allows one to use either the restriction or interpolation (its transpose)
8622   matrix to do the interpolation
8623 
8624 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8625 @*/
8626 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8627 {
8628   PetscInt M, N, Ny;
8629 
8630   PetscFunctionBegin;
8631   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8632   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8633   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8634   PetscCall(MatGetSize(A, &M, &N));
8635   PetscCall(VecGetSize(y, &Ny));
8636   if (M == Ny) {
8637     PetscCall(MatMult(A, x, y));
8638   } else {
8639     PetscCall(MatMultTranspose(A, x, y));
8640   }
8641   PetscFunctionReturn(PETSC_SUCCESS);
8642 }
8643 
8644 /*@
8645   MatRestrict - y = A*x or A'*x
8646 
8647   Neighbor-wise Collective
8648 
8649   Input Parameters:
8650 + A - the matrix
8651 - x - the vector to be restricted
8652 
8653   Output Parameter:
8654 . y - the resulting vector
8655 
8656   Level: intermediate
8657 
8658   Note:
8659   This allows one to use either the restriction or interpolation (its transpose)
8660   matrix to do the restriction
8661 
8662 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8663 @*/
8664 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8665 {
8666   PetscInt M, N, Ny;
8667 
8668   PetscFunctionBegin;
8669   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8670   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8671   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8672   PetscCall(MatGetSize(A, &M, &N));
8673   PetscCall(VecGetSize(y, &Ny));
8674   if (M == Ny) {
8675     PetscCall(MatMult(A, x, y));
8676   } else {
8677     PetscCall(MatMultTranspose(A, x, y));
8678   }
8679   PetscFunctionReturn(PETSC_SUCCESS);
8680 }
8681 
8682 /*@
8683   MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8684 
8685   Neighbor-wise Collective
8686 
8687   Input Parameters:
8688 + A - the matrix
8689 . x - the input dense matrix to be multiplied
8690 - w - the input dense matrix to be added to the result
8691 
8692   Output Parameter:
8693 . y - the output dense matrix
8694 
8695   Level: intermediate
8696 
8697   Note:
8698   This allows one to use either the restriction or interpolation (its transpose)
8699   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8700   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8701 
8702 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8703 @*/
8704 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8705 {
8706   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8707   PetscBool trans = PETSC_TRUE;
8708   MatReuse  reuse = MAT_INITIAL_MATRIX;
8709 
8710   PetscFunctionBegin;
8711   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8712   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8713   PetscValidType(x, 2);
8714   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8715   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8716   PetscCall(MatGetSize(A, &M, &N));
8717   PetscCall(MatGetSize(x, &Mx, &Nx));
8718   if (N == Mx) trans = PETSC_FALSE;
8719   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);
8720   Mo = trans ? N : M;
8721   if (*y) {
8722     PetscCall(MatGetSize(*y, &My, &Ny));
8723     if (Mo == My && Nx == Ny) {
8724       reuse = MAT_REUSE_MATRIX;
8725     } else {
8726       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);
8727       PetscCall(MatDestroy(y));
8728     }
8729   }
8730 
8731   if (w && *y == w) { /* this is to minimize changes in PCMG */
8732     PetscBool flg;
8733 
8734     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8735     if (w) {
8736       PetscInt My, Ny, Mw, Nw;
8737 
8738       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8739       PetscCall(MatGetSize(*y, &My, &Ny));
8740       PetscCall(MatGetSize(w, &Mw, &Nw));
8741       if (!flg || My != Mw || Ny != Nw) w = NULL;
8742     }
8743     if (!w) {
8744       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8745       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8746       PetscCall(PetscObjectDereference((PetscObject)w));
8747     } else {
8748       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8749     }
8750   }
8751   if (!trans) {
8752     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8753   } else {
8754     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8755   }
8756   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8757   PetscFunctionReturn(PETSC_SUCCESS);
8758 }
8759 
8760 /*@
8761   MatMatInterpolate - Y = A*X or A'*X
8762 
8763   Neighbor-wise Collective
8764 
8765   Input Parameters:
8766 + A - the matrix
8767 - x - the input dense matrix
8768 
8769   Output Parameter:
8770 . y - the output dense matrix
8771 
8772   Level: intermediate
8773 
8774   Note:
8775   This allows one to use either the restriction or interpolation (its transpose)
8776   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8777   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8778 
8779 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8780 @*/
8781 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8782 {
8783   PetscFunctionBegin;
8784   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8785   PetscFunctionReturn(PETSC_SUCCESS);
8786 }
8787 
8788 /*@
8789   MatMatRestrict - Y = A*X or A'*X
8790 
8791   Neighbor-wise Collective
8792 
8793   Input Parameters:
8794 + A - the matrix
8795 - x - the input dense matrix
8796 
8797   Output Parameter:
8798 . y - the output dense matrix
8799 
8800   Level: intermediate
8801 
8802   Note:
8803   This allows one to use either the restriction or interpolation (its transpose)
8804   matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8805   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8806 
8807 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8808 @*/
8809 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8810 {
8811   PetscFunctionBegin;
8812   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8813   PetscFunctionReturn(PETSC_SUCCESS);
8814 }
8815 
8816 /*@
8817   MatGetNullSpace - retrieves the null space of a matrix.
8818 
8819   Logically Collective
8820 
8821   Input Parameters:
8822 + mat    - the matrix
8823 - nullsp - the null space object
8824 
8825   Level: developer
8826 
8827 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8828 @*/
8829 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8830 {
8831   PetscFunctionBegin;
8832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8833   PetscAssertPointer(nullsp, 2);
8834   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8835   PetscFunctionReturn(PETSC_SUCCESS);
8836 }
8837 
8838 /*@
8839   MatSetNullSpace - attaches a null space to a matrix.
8840 
8841   Logically Collective
8842 
8843   Input Parameters:
8844 + mat    - the matrix
8845 - nullsp - the null space object
8846 
8847   Level: advanced
8848 
8849   Notes:
8850   This null space is used by the `KSP` linear solvers to solve singular systems.
8851 
8852   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`
8853 
8854   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
8855   to zero but the linear system will still be solved in a least squares sense.
8856 
8857   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8858   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).
8859   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
8860   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
8861   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).
8862   This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8863 
8864   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8865   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8866   routine also automatically calls `MatSetTransposeNullSpace()`.
8867 
8868   The user should call `MatNullSpaceDestroy()`.
8869 
8870 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8871           `KSPSetPCSide()`
8872 @*/
8873 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8874 {
8875   PetscFunctionBegin;
8876   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8877   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8878   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8879   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8880   mat->nullsp = nullsp;
8881   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8882   PetscFunctionReturn(PETSC_SUCCESS);
8883 }
8884 
8885 /*@
8886   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8887 
8888   Logically Collective
8889 
8890   Input Parameters:
8891 + mat    - the matrix
8892 - nullsp - the null space object
8893 
8894   Level: developer
8895 
8896 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8897 @*/
8898 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8899 {
8900   PetscFunctionBegin;
8901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8902   PetscValidType(mat, 1);
8903   PetscAssertPointer(nullsp, 2);
8904   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8905   PetscFunctionReturn(PETSC_SUCCESS);
8906 }
8907 
8908 /*@
8909   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8910 
8911   Logically Collective
8912 
8913   Input Parameters:
8914 + mat    - the matrix
8915 - nullsp - the null space object
8916 
8917   Level: advanced
8918 
8919   Notes:
8920   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8921 
8922   See `MatSetNullSpace()`
8923 
8924 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8925 @*/
8926 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8927 {
8928   PetscFunctionBegin;
8929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8930   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8931   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8932   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8933   mat->transnullsp = nullsp;
8934   PetscFunctionReturn(PETSC_SUCCESS);
8935 }
8936 
8937 /*@
8938   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8939   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8940 
8941   Logically Collective
8942 
8943   Input Parameters:
8944 + mat    - the matrix
8945 - nullsp - the null space object
8946 
8947   Level: advanced
8948 
8949   Notes:
8950   Overwrites any previous near null space that may have been attached
8951 
8952   You can remove the null space by calling this routine with an nullsp of `NULL`
8953 
8954 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8955 @*/
8956 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8957 {
8958   PetscFunctionBegin;
8959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8960   PetscValidType(mat, 1);
8961   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8962   MatCheckPreallocated(mat, 1);
8963   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8964   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8965   mat->nearnullsp = nullsp;
8966   PetscFunctionReturn(PETSC_SUCCESS);
8967 }
8968 
8969 /*@
8970   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8971 
8972   Not Collective
8973 
8974   Input Parameter:
8975 . mat - the matrix
8976 
8977   Output Parameter:
8978 . nullsp - the null space object, `NULL` if not set
8979 
8980   Level: advanced
8981 
8982 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8983 @*/
8984 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8985 {
8986   PetscFunctionBegin;
8987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8988   PetscValidType(mat, 1);
8989   PetscAssertPointer(nullsp, 2);
8990   MatCheckPreallocated(mat, 1);
8991   *nullsp = mat->nearnullsp;
8992   PetscFunctionReturn(PETSC_SUCCESS);
8993 }
8994 
8995 /*@C
8996   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8997 
8998   Collective
8999 
9000   Input Parameters:
9001 + mat  - the matrix
9002 . row  - row/column permutation
9003 - info - information on desired factorization process
9004 
9005   Level: developer
9006 
9007   Notes:
9008   Probably really in-place only when level of fill is zero, otherwise allocates
9009   new space to store factored matrix and deletes previous memory.
9010 
9011   Most users should employ the `KSP` interface for linear solvers
9012   instead of working directly with matrix algebra routines such as this.
9013   See, e.g., `KSPCreate()`.
9014 
9015   Developer Notes:
9016   The Fortran interface is not autogenerated as the
9017   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9018 
9019 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9020 @*/
9021 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9022 {
9023   PetscFunctionBegin;
9024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9025   PetscValidType(mat, 1);
9026   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9027   PetscAssertPointer(info, 3);
9028   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9029   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9030   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9031   MatCheckPreallocated(mat, 1);
9032   PetscUseTypeMethod(mat, iccfactor, row, info);
9033   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9034   PetscFunctionReturn(PETSC_SUCCESS);
9035 }
9036 
9037 /*@
9038   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9039   ghosted ones.
9040 
9041   Not Collective
9042 
9043   Input Parameters:
9044 + mat  - the matrix
9045 - diag - the diagonal values, including ghost ones
9046 
9047   Level: developer
9048 
9049   Notes:
9050   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9051 
9052   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9053 
9054 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9055 @*/
9056 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9057 {
9058   PetscMPIInt size;
9059 
9060   PetscFunctionBegin;
9061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9062   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9063   PetscValidType(mat, 1);
9064 
9065   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9066   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9067   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9068   if (size == 1) {
9069     PetscInt n, m;
9070     PetscCall(VecGetSize(diag, &n));
9071     PetscCall(MatGetSize(mat, NULL, &m));
9072     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9073     PetscCall(MatDiagonalScale(mat, NULL, diag));
9074   } else {
9075     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9076   }
9077   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9078   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9079   PetscFunctionReturn(PETSC_SUCCESS);
9080 }
9081 
9082 /*@
9083   MatGetInertia - Gets the inertia from a factored matrix
9084 
9085   Collective
9086 
9087   Input Parameter:
9088 . mat - the matrix
9089 
9090   Output Parameters:
9091 + nneg  - number of negative eigenvalues
9092 . nzero - number of zero eigenvalues
9093 - npos  - number of positive eigenvalues
9094 
9095   Level: advanced
9096 
9097   Note:
9098   Matrix must have been factored by `MatCholeskyFactor()`
9099 
9100 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9101 @*/
9102 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9103 {
9104   PetscFunctionBegin;
9105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9106   PetscValidType(mat, 1);
9107   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9108   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9109   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9110   PetscFunctionReturn(PETSC_SUCCESS);
9111 }
9112 
9113 /*@C
9114   MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9115 
9116   Neighbor-wise Collective
9117 
9118   Input Parameters:
9119 + mat - the factored matrix obtained with `MatGetFactor()`
9120 - b   - the right-hand-side vectors
9121 
9122   Output Parameter:
9123 . x - the result vectors
9124 
9125   Level: developer
9126 
9127   Note:
9128   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9129   call `MatSolves`(A,x,x).
9130 
9131 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9132 @*/
9133 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9134 {
9135   PetscFunctionBegin;
9136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9137   PetscValidType(mat, 1);
9138   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9139   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9140   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9141 
9142   MatCheckPreallocated(mat, 1);
9143   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9144   PetscUseTypeMethod(mat, solves, b, x);
9145   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9146   PetscFunctionReturn(PETSC_SUCCESS);
9147 }
9148 
9149 /*@
9150   MatIsSymmetric - Test whether a matrix is symmetric
9151 
9152   Collective
9153 
9154   Input Parameters:
9155 + A   - the matrix to test
9156 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9157 
9158   Output Parameter:
9159 . flg - the result
9160 
9161   Level: intermediate
9162 
9163   Notes:
9164   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9165 
9166   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9167 
9168   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9169   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9170 
9171 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9172           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9173 @*/
9174 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9175 {
9176   PetscFunctionBegin;
9177   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9178   PetscAssertPointer(flg, 3);
9179 
9180   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9181   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9182   else {
9183     PetscUseTypeMethod(A, issymmetric, tol, flg);
9184     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9185   }
9186   PetscFunctionReturn(PETSC_SUCCESS);
9187 }
9188 
9189 /*@
9190   MatIsHermitian - Test whether a matrix is Hermitian
9191 
9192   Collective
9193 
9194   Input Parameters:
9195 + A   - the matrix to test
9196 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9197 
9198   Output Parameter:
9199 . flg - the result
9200 
9201   Level: intermediate
9202 
9203   Notes:
9204   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9205 
9206   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9207 
9208   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9209   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9210 
9211 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9212           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9213 @*/
9214 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9215 {
9216   PetscFunctionBegin;
9217   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9218   PetscAssertPointer(flg, 3);
9219 
9220   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9221   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9222   else {
9223     PetscUseTypeMethod(A, ishermitian, tol, flg);
9224     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9225   }
9226   PetscFunctionReturn(PETSC_SUCCESS);
9227 }
9228 
9229 /*@
9230   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9231 
9232   Not Collective
9233 
9234   Input Parameter:
9235 . A - the matrix to check
9236 
9237   Output Parameters:
9238 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9239 - flg - the result (only valid if set is `PETSC_TRUE`)
9240 
9241   Level: advanced
9242 
9243   Notes:
9244   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9245   if you want it explicitly checked
9246 
9247   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9248   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9249 
9250 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9251 @*/
9252 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9253 {
9254   PetscFunctionBegin;
9255   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9256   PetscAssertPointer(set, 2);
9257   PetscAssertPointer(flg, 3);
9258   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9259     *set = PETSC_TRUE;
9260     *flg = PetscBool3ToBool(A->symmetric);
9261   } else {
9262     *set = PETSC_FALSE;
9263   }
9264   PetscFunctionReturn(PETSC_SUCCESS);
9265 }
9266 
9267 /*@
9268   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9269 
9270   Not Collective
9271 
9272   Input Parameter:
9273 . A - the matrix to check
9274 
9275   Output Parameters:
9276 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9277 - flg - the result (only valid if set is `PETSC_TRUE`)
9278 
9279   Level: advanced
9280 
9281   Notes:
9282   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9283 
9284   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9285   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9286 
9287 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9288 @*/
9289 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9290 {
9291   PetscFunctionBegin;
9292   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9293   PetscAssertPointer(set, 2);
9294   PetscAssertPointer(flg, 3);
9295   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9296     *set = PETSC_TRUE;
9297     *flg = PetscBool3ToBool(A->spd);
9298   } else {
9299     *set = PETSC_FALSE;
9300   }
9301   PetscFunctionReturn(PETSC_SUCCESS);
9302 }
9303 
9304 /*@
9305   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9306 
9307   Not Collective
9308 
9309   Input Parameter:
9310 . A - the matrix to check
9311 
9312   Output Parameters:
9313 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9314 - flg - the result (only valid if set is `PETSC_TRUE`)
9315 
9316   Level: advanced
9317 
9318   Notes:
9319   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9320   if you want it explicitly checked
9321 
9322   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9323   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9324 
9325 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9326 @*/
9327 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9328 {
9329   PetscFunctionBegin;
9330   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9331   PetscAssertPointer(set, 2);
9332   PetscAssertPointer(flg, 3);
9333   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9334     *set = PETSC_TRUE;
9335     *flg = PetscBool3ToBool(A->hermitian);
9336   } else {
9337     *set = PETSC_FALSE;
9338   }
9339   PetscFunctionReturn(PETSC_SUCCESS);
9340 }
9341 
9342 /*@
9343   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9344 
9345   Collective
9346 
9347   Input Parameter:
9348 . A - the matrix to test
9349 
9350   Output Parameter:
9351 . flg - the result
9352 
9353   Level: intermediate
9354 
9355   Notes:
9356   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9357 
9358   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
9359   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9360 
9361 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9362 @*/
9363 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9364 {
9365   PetscFunctionBegin;
9366   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9367   PetscAssertPointer(flg, 2);
9368   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9369     *flg = PetscBool3ToBool(A->structurally_symmetric);
9370   } else {
9371     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9372     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9373   }
9374   PetscFunctionReturn(PETSC_SUCCESS);
9375 }
9376 
9377 /*@
9378   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9379 
9380   Not Collective
9381 
9382   Input Parameter:
9383 . A - the matrix to check
9384 
9385   Output Parameters:
9386 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9387 - flg - the result (only valid if set is PETSC_TRUE)
9388 
9389   Level: advanced
9390 
9391   Notes:
9392   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
9393   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9394 
9395   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9396 
9397 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9398 @*/
9399 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9400 {
9401   PetscFunctionBegin;
9402   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9403   PetscAssertPointer(set, 2);
9404   PetscAssertPointer(flg, 3);
9405   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9406     *set = PETSC_TRUE;
9407     *flg = PetscBool3ToBool(A->structurally_symmetric);
9408   } else {
9409     *set = PETSC_FALSE;
9410   }
9411   PetscFunctionReturn(PETSC_SUCCESS);
9412 }
9413 
9414 /*@
9415   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9416   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9417 
9418   Not Collective
9419 
9420   Input Parameter:
9421 . mat - the matrix
9422 
9423   Output Parameters:
9424 + nstash    - the size of the stash
9425 . reallocs  - the number of additional mallocs incurred.
9426 . bnstash   - the size of the block stash
9427 - breallocs - the number of additional mallocs incurred.in the block stash
9428 
9429   Level: advanced
9430 
9431 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9432 @*/
9433 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9434 {
9435   PetscFunctionBegin;
9436   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9437   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9438   PetscFunctionReturn(PETSC_SUCCESS);
9439 }
9440 
9441 /*@C
9442   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9443   parallel layout, `PetscLayout` for rows and columns
9444 
9445   Collective
9446 
9447   Input Parameter:
9448 . mat - the matrix
9449 
9450   Output Parameters:
9451 + right - (optional) vector that the matrix can be multiplied against
9452 - left  - (optional) vector that the matrix vector product can be stored in
9453 
9454   Level: advanced
9455 
9456   Notes:
9457   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()`.
9458 
9459   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9460 
9461 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9462 @*/
9463 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9464 {
9465   PetscFunctionBegin;
9466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9467   PetscValidType(mat, 1);
9468   if (mat->ops->getvecs) {
9469     PetscUseTypeMethod(mat, getvecs, right, left);
9470   } else {
9471     if (right) {
9472       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9473       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9474       PetscCall(VecSetType(*right, mat->defaultvectype));
9475 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9476       if (mat->boundtocpu && mat->bindingpropagates) {
9477         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9478         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9479       }
9480 #endif
9481     }
9482     if (left) {
9483       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9484       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9485       PetscCall(VecSetType(*left, mat->defaultvectype));
9486 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9487       if (mat->boundtocpu && mat->bindingpropagates) {
9488         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9489         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9490       }
9491 #endif
9492     }
9493   }
9494   PetscFunctionReturn(PETSC_SUCCESS);
9495 }
9496 
9497 /*@C
9498   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9499   with default values.
9500 
9501   Not Collective
9502 
9503   Input Parameter:
9504 . info - the `MatFactorInfo` data structure
9505 
9506   Level: developer
9507 
9508   Notes:
9509   The solvers are generally used through the `KSP` and `PC` objects, for example
9510   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9511 
9512   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9513 
9514   Developer Notes:
9515   The Fortran interface is not autogenerated as the
9516   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9517 
9518 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9519 @*/
9520 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9521 {
9522   PetscFunctionBegin;
9523   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9524   PetscFunctionReturn(PETSC_SUCCESS);
9525 }
9526 
9527 /*@
9528   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9529 
9530   Collective
9531 
9532   Input Parameters:
9533 + mat - the factored matrix
9534 - is  - the index set defining the Schur indices (0-based)
9535 
9536   Level: advanced
9537 
9538   Notes:
9539   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9540 
9541   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9542 
9543   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9544 
9545 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9546           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9547 @*/
9548 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9549 {
9550   PetscErrorCode (*f)(Mat, IS);
9551 
9552   PetscFunctionBegin;
9553   PetscValidType(mat, 1);
9554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9555   PetscValidType(is, 2);
9556   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9557   PetscCheckSameComm(mat, 1, is, 2);
9558   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9559   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9560   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9561   PetscCall(MatDestroy(&mat->schur));
9562   PetscCall((*f)(mat, is));
9563   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9564   PetscFunctionReturn(PETSC_SUCCESS);
9565 }
9566 
9567 /*@
9568   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9569 
9570   Logically Collective
9571 
9572   Input Parameters:
9573 + F      - the factored matrix obtained by calling `MatGetFactor()`
9574 . S      - location where to return the Schur complement, can be `NULL`
9575 - status - the status of the Schur complement matrix, can be `NULL`
9576 
9577   Level: advanced
9578 
9579   Notes:
9580   You must call `MatFactorSetSchurIS()` before calling this routine.
9581 
9582   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9583 
9584   The routine provides a copy of the Schur matrix stored within the solver data structures.
9585   The caller must destroy the object when it is no longer needed.
9586   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9587 
9588   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)
9589 
9590   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9591 
9592   Developer Notes:
9593   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9594   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9595 
9596 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9597 @*/
9598 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9599 {
9600   PetscFunctionBegin;
9601   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9602   if (S) PetscAssertPointer(S, 2);
9603   if (status) PetscAssertPointer(status, 3);
9604   if (S) {
9605     PetscErrorCode (*f)(Mat, Mat *);
9606 
9607     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9608     if (f) {
9609       PetscCall((*f)(F, S));
9610     } else {
9611       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9612     }
9613   }
9614   if (status) *status = F->schur_status;
9615   PetscFunctionReturn(PETSC_SUCCESS);
9616 }
9617 
9618 /*@
9619   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9620 
9621   Logically Collective
9622 
9623   Input Parameters:
9624 + F      - the factored matrix obtained by calling `MatGetFactor()`
9625 . S      - location where to return the Schur complement, can be `NULL`
9626 - status - the status of the Schur complement matrix, can be `NULL`
9627 
9628   Level: advanced
9629 
9630   Notes:
9631   You must call `MatFactorSetSchurIS()` before calling this routine.
9632 
9633   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9634 
9635   The routine returns a the Schur Complement stored within the data structures of the solver.
9636 
9637   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9638 
9639   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9640 
9641   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9642 
9643   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9644 
9645 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9646 @*/
9647 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9648 {
9649   PetscFunctionBegin;
9650   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9651   if (S) {
9652     PetscAssertPointer(S, 2);
9653     *S = F->schur;
9654   }
9655   if (status) {
9656     PetscAssertPointer(status, 3);
9657     *status = F->schur_status;
9658   }
9659   PetscFunctionReturn(PETSC_SUCCESS);
9660 }
9661 
9662 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9663 {
9664   Mat S = F->schur;
9665 
9666   PetscFunctionBegin;
9667   switch (F->schur_status) {
9668   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9669   case MAT_FACTOR_SCHUR_INVERTED:
9670     if (S) {
9671       S->ops->solve             = NULL;
9672       S->ops->matsolve          = NULL;
9673       S->ops->solvetranspose    = NULL;
9674       S->ops->matsolvetranspose = NULL;
9675       S->ops->solveadd          = NULL;
9676       S->ops->solvetransposeadd = NULL;
9677       S->factortype             = MAT_FACTOR_NONE;
9678       PetscCall(PetscFree(S->solvertype));
9679     }
9680   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9681     break;
9682   default:
9683     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9684   }
9685   PetscFunctionReturn(PETSC_SUCCESS);
9686 }
9687 
9688 /*@
9689   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9690 
9691   Logically Collective
9692 
9693   Input Parameters:
9694 + F      - the factored matrix obtained by calling `MatGetFactor()`
9695 . S      - location where the Schur complement is stored
9696 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9697 
9698   Level: advanced
9699 
9700 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9701 @*/
9702 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9703 {
9704   PetscFunctionBegin;
9705   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9706   if (S) {
9707     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9708     *S = NULL;
9709   }
9710   F->schur_status = status;
9711   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9712   PetscFunctionReturn(PETSC_SUCCESS);
9713 }
9714 
9715 /*@
9716   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9717 
9718   Logically Collective
9719 
9720   Input Parameters:
9721 + F   - the factored matrix obtained by calling `MatGetFactor()`
9722 . rhs - location where the right hand side of the Schur complement system is stored
9723 - sol - location where the solution of the Schur complement system has to be returned
9724 
9725   Level: advanced
9726 
9727   Notes:
9728   The sizes of the vectors should match the size of the Schur complement
9729 
9730   Must be called after `MatFactorSetSchurIS()`
9731 
9732 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9733 @*/
9734 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9735 {
9736   PetscFunctionBegin;
9737   PetscValidType(F, 1);
9738   PetscValidType(rhs, 2);
9739   PetscValidType(sol, 3);
9740   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9741   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9742   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9743   PetscCheckSameComm(F, 1, rhs, 2);
9744   PetscCheckSameComm(F, 1, sol, 3);
9745   PetscCall(MatFactorFactorizeSchurComplement(F));
9746   switch (F->schur_status) {
9747   case MAT_FACTOR_SCHUR_FACTORED:
9748     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9749     break;
9750   case MAT_FACTOR_SCHUR_INVERTED:
9751     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9752     break;
9753   default:
9754     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9755   }
9756   PetscFunctionReturn(PETSC_SUCCESS);
9757 }
9758 
9759 /*@
9760   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9761 
9762   Logically Collective
9763 
9764   Input Parameters:
9765 + F   - the factored matrix obtained by calling `MatGetFactor()`
9766 . rhs - location where the right hand side of the Schur complement system is stored
9767 - sol - location where the solution of the Schur complement system has to be returned
9768 
9769   Level: advanced
9770 
9771   Notes:
9772   The sizes of the vectors should match the size of the Schur complement
9773 
9774   Must be called after `MatFactorSetSchurIS()`
9775 
9776 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9777 @*/
9778 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9779 {
9780   PetscFunctionBegin;
9781   PetscValidType(F, 1);
9782   PetscValidType(rhs, 2);
9783   PetscValidType(sol, 3);
9784   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9785   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9786   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9787   PetscCheckSameComm(F, 1, rhs, 2);
9788   PetscCheckSameComm(F, 1, sol, 3);
9789   PetscCall(MatFactorFactorizeSchurComplement(F));
9790   switch (F->schur_status) {
9791   case MAT_FACTOR_SCHUR_FACTORED:
9792     PetscCall(MatSolve(F->schur, rhs, sol));
9793     break;
9794   case MAT_FACTOR_SCHUR_INVERTED:
9795     PetscCall(MatMult(F->schur, rhs, sol));
9796     break;
9797   default:
9798     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9799   }
9800   PetscFunctionReturn(PETSC_SUCCESS);
9801 }
9802 
9803 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9804 #if PetscDefined(HAVE_CUDA)
9805 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9806 #endif
9807 
9808 /* Schur status updated in the interface */
9809 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9810 {
9811   Mat S = F->schur;
9812 
9813   PetscFunctionBegin;
9814   if (S) {
9815     PetscMPIInt size;
9816     PetscBool   isdense, isdensecuda;
9817 
9818     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9819     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9820     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9821     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9822     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9823     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9824     if (isdense) {
9825       PetscCall(MatSeqDenseInvertFactors_Private(S));
9826     } else if (isdensecuda) {
9827 #if defined(PETSC_HAVE_CUDA)
9828       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9829 #endif
9830     }
9831     // HIP??????????????
9832     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9833   }
9834   PetscFunctionReturn(PETSC_SUCCESS);
9835 }
9836 
9837 /*@
9838   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9839 
9840   Logically Collective
9841 
9842   Input Parameter:
9843 . F - the factored matrix obtained by calling `MatGetFactor()`
9844 
9845   Level: advanced
9846 
9847   Notes:
9848   Must be called after `MatFactorSetSchurIS()`.
9849 
9850   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9851 
9852 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9853 @*/
9854 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9855 {
9856   PetscFunctionBegin;
9857   PetscValidType(F, 1);
9858   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9859   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9860   PetscCall(MatFactorFactorizeSchurComplement(F));
9861   PetscCall(MatFactorInvertSchurComplement_Private(F));
9862   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9863   PetscFunctionReturn(PETSC_SUCCESS);
9864 }
9865 
9866 /*@
9867   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9868 
9869   Logically Collective
9870 
9871   Input Parameter:
9872 . F - the factored matrix obtained by calling `MatGetFactor()`
9873 
9874   Level: advanced
9875 
9876   Note:
9877   Must be called after `MatFactorSetSchurIS()`
9878 
9879 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9880 @*/
9881 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9882 {
9883   MatFactorInfo info;
9884 
9885   PetscFunctionBegin;
9886   PetscValidType(F, 1);
9887   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9888   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9889   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9890   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9891   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9892     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9893   } else {
9894     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9895   }
9896   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9897   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9898   PetscFunctionReturn(PETSC_SUCCESS);
9899 }
9900 
9901 /*@
9902   MatPtAP - Creates the matrix product C = P^T * A * P
9903 
9904   Neighbor-wise Collective
9905 
9906   Input Parameters:
9907 + A     - the matrix
9908 . P     - the projection matrix
9909 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9910 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9911           if the result is a dense matrix this is irrelevant
9912 
9913   Output Parameter:
9914 . C - the product matrix
9915 
9916   Level: intermediate
9917 
9918   Notes:
9919   C will be created and must be destroyed by the user with `MatDestroy()`.
9920 
9921   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9922 
9923   Developer Notes:
9924   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9925 
9926 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9927 @*/
9928 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9929 {
9930   PetscFunctionBegin;
9931   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9932   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9933 
9934   if (scall == MAT_INITIAL_MATRIX) {
9935     PetscCall(MatProductCreate(A, P, NULL, C));
9936     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9937     PetscCall(MatProductSetAlgorithm(*C, "default"));
9938     PetscCall(MatProductSetFill(*C, fill));
9939 
9940     (*C)->product->api_user = PETSC_TRUE;
9941     PetscCall(MatProductSetFromOptions(*C));
9942     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);
9943     PetscCall(MatProductSymbolic(*C));
9944   } else { /* scall == MAT_REUSE_MATRIX */
9945     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9946   }
9947 
9948   PetscCall(MatProductNumeric(*C));
9949   (*C)->symmetric = A->symmetric;
9950   (*C)->spd       = A->spd;
9951   PetscFunctionReturn(PETSC_SUCCESS);
9952 }
9953 
9954 /*@
9955   MatRARt - Creates the matrix product C = R * A * R^T
9956 
9957   Neighbor-wise Collective
9958 
9959   Input Parameters:
9960 + A     - the matrix
9961 . R     - the projection matrix
9962 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9963 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9964           if the result is a dense matrix this is irrelevant
9965 
9966   Output Parameter:
9967 . C - the product matrix
9968 
9969   Level: intermediate
9970 
9971   Notes:
9972   C will be created and must be destroyed by the user with `MatDestroy()`.
9973 
9974   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9975 
9976   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9977   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9978   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9979   We recommend using MatPtAP().
9980 
9981 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9982 @*/
9983 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9984 {
9985   PetscFunctionBegin;
9986   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9987   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9988 
9989   if (scall == MAT_INITIAL_MATRIX) {
9990     PetscCall(MatProductCreate(A, R, NULL, C));
9991     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9992     PetscCall(MatProductSetAlgorithm(*C, "default"));
9993     PetscCall(MatProductSetFill(*C, fill));
9994 
9995     (*C)->product->api_user = PETSC_TRUE;
9996     PetscCall(MatProductSetFromOptions(*C));
9997     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);
9998     PetscCall(MatProductSymbolic(*C));
9999   } else { /* scall == MAT_REUSE_MATRIX */
10000     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10001   }
10002 
10003   PetscCall(MatProductNumeric(*C));
10004   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10005   PetscFunctionReturn(PETSC_SUCCESS);
10006 }
10007 
10008 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10009 {
10010   PetscFunctionBegin;
10011   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10012 
10013   if (scall == MAT_INITIAL_MATRIX) {
10014     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10015     PetscCall(MatProductCreate(A, B, NULL, C));
10016     PetscCall(MatProductSetType(*C, ptype));
10017     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10018     PetscCall(MatProductSetFill(*C, fill));
10019 
10020     (*C)->product->api_user = PETSC_TRUE;
10021     PetscCall(MatProductSetFromOptions(*C));
10022     PetscCall(MatProductSymbolic(*C));
10023   } else { /* scall == MAT_REUSE_MATRIX */
10024     Mat_Product *product = (*C)->product;
10025     PetscBool    isdense;
10026 
10027     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10028     if (isdense && product && product->type != ptype) {
10029       PetscCall(MatProductClear(*C));
10030       product = NULL;
10031     }
10032     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10033     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10034       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10035       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10036       product           = (*C)->product;
10037       product->fill     = fill;
10038       product->api_user = PETSC_TRUE;
10039       product->clear    = PETSC_TRUE;
10040 
10041       PetscCall(MatProductSetType(*C, ptype));
10042       PetscCall(MatProductSetFromOptions(*C));
10043       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);
10044       PetscCall(MatProductSymbolic(*C));
10045     } else { /* user may change input matrices A or B when REUSE */
10046       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10047     }
10048   }
10049   PetscCall(MatProductNumeric(*C));
10050   PetscFunctionReturn(PETSC_SUCCESS);
10051 }
10052 
10053 /*@
10054   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10055 
10056   Neighbor-wise Collective
10057 
10058   Input Parameters:
10059 + A     - the left matrix
10060 . B     - the right matrix
10061 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10062 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10063           if the result is a dense matrix this is irrelevant
10064 
10065   Output Parameter:
10066 . C - the product matrix
10067 
10068   Notes:
10069   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10070 
10071   `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
10072   call to this function with `MAT_INITIAL_MATRIX`.
10073 
10074   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10075 
10076   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`,
10077   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10078 
10079   Example of Usage:
10080 .vb
10081      MatProductCreate(A,B,NULL,&C);
10082      MatProductSetType(C,MATPRODUCT_AB);
10083      MatProductSymbolic(C);
10084      MatProductNumeric(C); // compute C=A * B
10085      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10086      MatProductNumeric(C);
10087      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10088      MatProductNumeric(C);
10089 .ve
10090 
10091   Level: intermediate
10092 
10093 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10094 @*/
10095 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10096 {
10097   PetscFunctionBegin;
10098   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10099   PetscFunctionReturn(PETSC_SUCCESS);
10100 }
10101 
10102 /*@
10103   MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10104 
10105   Neighbor-wise Collective
10106 
10107   Input Parameters:
10108 + A     - the left matrix
10109 . B     - the right matrix
10110 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10111 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10112 
10113   Output Parameter:
10114 . C - the product matrix
10115 
10116   Level: intermediate
10117 
10118   Notes:
10119   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10120 
10121   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10122 
10123   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10124   actually needed.
10125 
10126   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10127   and for pairs of `MATMPIDENSE` matrices.
10128 
10129   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10130 
10131   Options Database Keys:
10132 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10133               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10134               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10135 
10136 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10137 @*/
10138 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10139 {
10140   PetscFunctionBegin;
10141   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10142   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10143   PetscFunctionReturn(PETSC_SUCCESS);
10144 }
10145 
10146 /*@
10147   MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10148 
10149   Neighbor-wise Collective
10150 
10151   Input Parameters:
10152 + A     - the left matrix
10153 . B     - the right matrix
10154 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10155 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10156 
10157   Output Parameter:
10158 . C - the product matrix
10159 
10160   Level: intermediate
10161 
10162   Notes:
10163   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10164 
10165   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10166 
10167   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10168 
10169   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10170   actually needed.
10171 
10172   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10173   which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10174 
10175 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10176 @*/
10177 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10178 {
10179   PetscFunctionBegin;
10180   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10181   PetscFunctionReturn(PETSC_SUCCESS);
10182 }
10183 
10184 /*@
10185   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10186 
10187   Neighbor-wise Collective
10188 
10189   Input Parameters:
10190 + A     - the left matrix
10191 . B     - the middle matrix
10192 . C     - the right matrix
10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10194 - 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
10195           if the result is a dense matrix this is irrelevant
10196 
10197   Output Parameter:
10198 . D - the product matrix
10199 
10200   Level: intermediate
10201 
10202   Notes:
10203   Unless scall is `MAT_REUSE_MATRIX` D will be created.
10204 
10205   `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10206 
10207   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10208 
10209   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10210   actually needed.
10211 
10212   If you have many matrices with the same non-zero structure to multiply, you
10213   should use `MAT_REUSE_MATRIX` in all calls but the first
10214 
10215 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10216 @*/
10217 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10218 {
10219   PetscFunctionBegin;
10220   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10221   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10222 
10223   if (scall == MAT_INITIAL_MATRIX) {
10224     PetscCall(MatProductCreate(A, B, C, D));
10225     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10226     PetscCall(MatProductSetAlgorithm(*D, "default"));
10227     PetscCall(MatProductSetFill(*D, fill));
10228 
10229     (*D)->product->api_user = PETSC_TRUE;
10230     PetscCall(MatProductSetFromOptions(*D));
10231     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,
10232                ((PetscObject)C)->type_name);
10233     PetscCall(MatProductSymbolic(*D));
10234   } else { /* user may change input matrices when REUSE */
10235     PetscCall(MatProductReplaceMats(A, B, C, *D));
10236   }
10237   PetscCall(MatProductNumeric(*D));
10238   PetscFunctionReturn(PETSC_SUCCESS);
10239 }
10240 
10241 /*@
10242   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10243 
10244   Collective
10245 
10246   Input Parameters:
10247 + mat      - the matrix
10248 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10249 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10250 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10251 
10252   Output Parameter:
10253 . matredundant - redundant matrix
10254 
10255   Level: advanced
10256 
10257   Notes:
10258   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10259   original matrix has not changed from that last call to MatCreateRedundantMatrix().
10260 
10261   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10262   calling it.
10263 
10264   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10265 
10266 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10267 @*/
10268 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10269 {
10270   MPI_Comm       comm;
10271   PetscMPIInt    size;
10272   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10273   Mat_Redundant *redund     = NULL;
10274   PetscSubcomm   psubcomm   = NULL;
10275   MPI_Comm       subcomm_in = subcomm;
10276   Mat           *matseq;
10277   IS             isrow, iscol;
10278   PetscBool      newsubcomm = PETSC_FALSE;
10279 
10280   PetscFunctionBegin;
10281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10282   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10283     PetscAssertPointer(*matredundant, 5);
10284     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10285   }
10286 
10287   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10288   if (size == 1 || nsubcomm == 1) {
10289     if (reuse == MAT_INITIAL_MATRIX) {
10290       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10291     } else {
10292       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");
10293       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10294     }
10295     PetscFunctionReturn(PETSC_SUCCESS);
10296   }
10297 
10298   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10299   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10300   MatCheckPreallocated(mat, 1);
10301 
10302   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10303   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10304     /* create psubcomm, then get subcomm */
10305     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10306     PetscCallMPI(MPI_Comm_size(comm, &size));
10307     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10308 
10309     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10310     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10311     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10312     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10313     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10314     newsubcomm = PETSC_TRUE;
10315     PetscCall(PetscSubcommDestroy(&psubcomm));
10316   }
10317 
10318   /* get isrow, iscol and a local sequential matrix matseq[0] */
10319   if (reuse == MAT_INITIAL_MATRIX) {
10320     mloc_sub = PETSC_DECIDE;
10321     nloc_sub = PETSC_DECIDE;
10322     if (bs < 1) {
10323       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10324       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10325     } else {
10326       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10327       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10328     }
10329     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10330     rstart = rend - mloc_sub;
10331     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10332     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10333     PetscCall(ISSetIdentity(iscol));
10334   } else { /* reuse == MAT_REUSE_MATRIX */
10335     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");
10336     /* retrieve subcomm */
10337     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10338     redund = (*matredundant)->redundant;
10339     isrow  = redund->isrow;
10340     iscol  = redund->iscol;
10341     matseq = redund->matseq;
10342   }
10343   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10344 
10345   /* get matredundant over subcomm */
10346   if (reuse == MAT_INITIAL_MATRIX) {
10347     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10348 
10349     /* create a supporting struct and attach it to C for reuse */
10350     PetscCall(PetscNew(&redund));
10351     (*matredundant)->redundant = redund;
10352     redund->isrow              = isrow;
10353     redund->iscol              = iscol;
10354     redund->matseq             = matseq;
10355     if (newsubcomm) {
10356       redund->subcomm = subcomm;
10357     } else {
10358       redund->subcomm = MPI_COMM_NULL;
10359     }
10360   } else {
10361     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10362   }
10363 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10364   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10365     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10366     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10367   }
10368 #endif
10369   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10370   PetscFunctionReturn(PETSC_SUCCESS);
10371 }
10372 
10373 /*@C
10374   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10375   a given `Mat`. Each submatrix can span multiple procs.
10376 
10377   Collective
10378 
10379   Input Parameters:
10380 + mat     - the matrix
10381 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10382 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10383 
10384   Output Parameter:
10385 . subMat - parallel sub-matrices each spanning a given `subcomm`
10386 
10387   Level: advanced
10388 
10389   Notes:
10390   The submatrix partition across processors is dictated by `subComm` a
10391   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10392   is not restricted to be grouped with consecutive original ranks.
10393 
10394   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10395   map directly to the layout of the original matrix [wrt the local
10396   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10397   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10398   the `subMat`. However the offDiagMat looses some columns - and this is
10399   reconstructed with `MatSetValues()`
10400 
10401   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10402 
10403 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10404 @*/
10405 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10406 {
10407   PetscMPIInt commsize, subCommSize;
10408 
10409   PetscFunctionBegin;
10410   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10411   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10412   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10413 
10414   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");
10415   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10416   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10417   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10418   PetscFunctionReturn(PETSC_SUCCESS);
10419 }
10420 
10421 /*@
10422   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10423 
10424   Not Collective
10425 
10426   Input Parameters:
10427 + mat   - matrix to extract local submatrix from
10428 . isrow - local row indices for submatrix
10429 - iscol - local column indices for submatrix
10430 
10431   Output Parameter:
10432 . submat - the submatrix
10433 
10434   Level: intermediate
10435 
10436   Notes:
10437   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10438 
10439   Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10440   the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10441 
10442   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10443   `MatSetValuesBlockedLocal()` will also be implemented.
10444 
10445   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10446   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10447 
10448 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10449 @*/
10450 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10451 {
10452   PetscFunctionBegin;
10453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10454   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10455   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10456   PetscCheckSameComm(isrow, 2, iscol, 3);
10457   PetscAssertPointer(submat, 4);
10458   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10459 
10460   if (mat->ops->getlocalsubmatrix) {
10461     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10462   } else {
10463     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10464   }
10465   PetscFunctionReturn(PETSC_SUCCESS);
10466 }
10467 
10468 /*@
10469   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10470 
10471   Not Collective
10472 
10473   Input Parameters:
10474 + mat    - matrix to extract local submatrix from
10475 . isrow  - local row indices for submatrix
10476 . iscol  - local column indices for submatrix
10477 - submat - the submatrix
10478 
10479   Level: intermediate
10480 
10481 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10482 @*/
10483 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10484 {
10485   PetscFunctionBegin;
10486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10487   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10488   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10489   PetscCheckSameComm(isrow, 2, iscol, 3);
10490   PetscAssertPointer(submat, 4);
10491   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10492 
10493   if (mat->ops->restorelocalsubmatrix) {
10494     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10495   } else {
10496     PetscCall(MatDestroy(submat));
10497   }
10498   *submat = NULL;
10499   PetscFunctionReturn(PETSC_SUCCESS);
10500 }
10501 
10502 /*@
10503   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10504 
10505   Collective
10506 
10507   Input Parameter:
10508 . mat - the matrix
10509 
10510   Output Parameter:
10511 . is - if any rows have zero diagonals this contains the list of them
10512 
10513   Level: developer
10514 
10515 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10516 @*/
10517 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10518 {
10519   PetscFunctionBegin;
10520   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10521   PetscValidType(mat, 1);
10522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10524 
10525   if (!mat->ops->findzerodiagonals) {
10526     Vec                diag;
10527     const PetscScalar *a;
10528     PetscInt          *rows;
10529     PetscInt           rStart, rEnd, r, nrow = 0;
10530 
10531     PetscCall(MatCreateVecs(mat, &diag, NULL));
10532     PetscCall(MatGetDiagonal(mat, diag));
10533     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10534     PetscCall(VecGetArrayRead(diag, &a));
10535     for (r = 0; r < rEnd - rStart; ++r)
10536       if (a[r] == 0.0) ++nrow;
10537     PetscCall(PetscMalloc1(nrow, &rows));
10538     nrow = 0;
10539     for (r = 0; r < rEnd - rStart; ++r)
10540       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10541     PetscCall(VecRestoreArrayRead(diag, &a));
10542     PetscCall(VecDestroy(&diag));
10543     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10544   } else {
10545     PetscUseTypeMethod(mat, findzerodiagonals, is);
10546   }
10547   PetscFunctionReturn(PETSC_SUCCESS);
10548 }
10549 
10550 /*@
10551   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10552 
10553   Collective
10554 
10555   Input Parameter:
10556 . mat - the matrix
10557 
10558   Output Parameter:
10559 . is - contains the list of rows with off block diagonal entries
10560 
10561   Level: developer
10562 
10563 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10564 @*/
10565 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10566 {
10567   PetscFunctionBegin;
10568   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10569   PetscValidType(mat, 1);
10570   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10571   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10572 
10573   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10574   PetscFunctionReturn(PETSC_SUCCESS);
10575 }
10576 
10577 /*@C
10578   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10579 
10580   Collective; No Fortran Support
10581 
10582   Input Parameter:
10583 . mat - the matrix
10584 
10585   Output Parameter:
10586 . values - the block inverses in column major order (FORTRAN-like)
10587 
10588   Level: advanced
10589 
10590   Notes:
10591   The size of the blocks is determined by the block size of the matrix.
10592 
10593   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10594 
10595   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10596 
10597 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10598 @*/
10599 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10600 {
10601   PetscFunctionBegin;
10602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10603   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10604   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10605   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10606   PetscFunctionReturn(PETSC_SUCCESS);
10607 }
10608 
10609 /*@C
10610   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10611 
10612   Collective; No Fortran Support
10613 
10614   Input Parameters:
10615 + mat     - the matrix
10616 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10617 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10618 
10619   Output Parameter:
10620 . values - the block inverses in column major order (FORTRAN-like)
10621 
10622   Level: advanced
10623 
10624   Notes:
10625   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10626 
10627   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10628 
10629 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10630 @*/
10631 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10632 {
10633   PetscFunctionBegin;
10634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10635   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10636   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10637   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10638   PetscFunctionReturn(PETSC_SUCCESS);
10639 }
10640 
10641 /*@
10642   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10643 
10644   Collective
10645 
10646   Input Parameters:
10647 + A - the matrix
10648 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10649 
10650   Level: advanced
10651 
10652   Note:
10653   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10654 
10655 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10656 @*/
10657 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10658 {
10659   const PetscScalar *vals;
10660   PetscInt          *dnnz;
10661   PetscInt           m, rstart, rend, bs, i, j;
10662 
10663   PetscFunctionBegin;
10664   PetscCall(MatInvertBlockDiagonal(A, &vals));
10665   PetscCall(MatGetBlockSize(A, &bs));
10666   PetscCall(MatGetLocalSize(A, &m, NULL));
10667   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10668   PetscCall(PetscMalloc1(m / bs, &dnnz));
10669   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10670   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10671   PetscCall(PetscFree(dnnz));
10672   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10673   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10674   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10675   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10676   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10677   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10678   PetscFunctionReturn(PETSC_SUCCESS);
10679 }
10680 
10681 /*@C
10682   MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10683   via `MatTransposeColoringCreate()`.
10684 
10685   Collective
10686 
10687   Input Parameter:
10688 . c - coloring context
10689 
10690   Level: intermediate
10691 
10692 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10693 @*/
10694 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10695 {
10696   MatTransposeColoring matcolor = *c;
10697 
10698   PetscFunctionBegin;
10699   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10700   if (--((PetscObject)matcolor)->refct > 0) {
10701     matcolor = NULL;
10702     PetscFunctionReturn(PETSC_SUCCESS);
10703   }
10704 
10705   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10706   PetscCall(PetscFree(matcolor->rows));
10707   PetscCall(PetscFree(matcolor->den2sp));
10708   PetscCall(PetscFree(matcolor->colorforcol));
10709   PetscCall(PetscFree(matcolor->columns));
10710   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10711   PetscCall(PetscHeaderDestroy(c));
10712   PetscFunctionReturn(PETSC_SUCCESS);
10713 }
10714 
10715 /*@C
10716   MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10717   a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10718   `MatTransposeColoring` to sparse B.
10719 
10720   Collective
10721 
10722   Input Parameters:
10723 + coloring - coloring context created with `MatTransposeColoringCreate()`
10724 - B        - sparse matrix
10725 
10726   Output Parameter:
10727 . Btdense - dense matrix B^T
10728 
10729   Level: developer
10730 
10731   Note:
10732   These are used internally for some implementations of `MatRARt()`
10733 
10734 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10735 @*/
10736 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10737 {
10738   PetscFunctionBegin;
10739   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10740   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10741   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10742 
10743   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10744   PetscFunctionReturn(PETSC_SUCCESS);
10745 }
10746 
10747 /*@C
10748   MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10749   a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10750   in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10751   `Csp` from `Cden`.
10752 
10753   Collective
10754 
10755   Input Parameters:
10756 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10757 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10758 
10759   Output Parameter:
10760 . Csp - sparse matrix
10761 
10762   Level: developer
10763 
10764   Note:
10765   These are used internally for some implementations of `MatRARt()`
10766 
10767 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10768 @*/
10769 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10770 {
10771   PetscFunctionBegin;
10772   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10773   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10774   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10775 
10776   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10777   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10778   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10779   PetscFunctionReturn(PETSC_SUCCESS);
10780 }
10781 
10782 /*@C
10783   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10784 
10785   Collective
10786 
10787   Input Parameters:
10788 + mat        - the matrix product C
10789 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10790 
10791   Output Parameter:
10792 . color - the new coloring context
10793 
10794   Level: intermediate
10795 
10796 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10797           `MatTransColoringApplyDenToSp()`
10798 @*/
10799 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10800 {
10801   MatTransposeColoring c;
10802   MPI_Comm             comm;
10803 
10804   PetscFunctionBegin;
10805   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10806   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10807   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10808 
10809   c->ctype = iscoloring->ctype;
10810   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10811 
10812   *color = c;
10813   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10814   PetscFunctionReturn(PETSC_SUCCESS);
10815 }
10816 
10817 /*@
10818   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10819   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10820   same, otherwise it will be larger
10821 
10822   Not Collective
10823 
10824   Input Parameter:
10825 . mat - the matrix
10826 
10827   Output Parameter:
10828 . state - the current state
10829 
10830   Level: intermediate
10831 
10832   Notes:
10833   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10834   different matrices
10835 
10836   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10837 
10838   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10839 
10840 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10841 @*/
10842 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10843 {
10844   PetscFunctionBegin;
10845   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10846   *state = mat->nonzerostate;
10847   PetscFunctionReturn(PETSC_SUCCESS);
10848 }
10849 
10850 /*@
10851   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10852   matrices from each processor
10853 
10854   Collective
10855 
10856   Input Parameters:
10857 + comm   - the communicators the parallel matrix will live on
10858 . seqmat - the input sequential matrices
10859 . n      - number of local columns (or `PETSC_DECIDE`)
10860 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10861 
10862   Output Parameter:
10863 . mpimat - the parallel matrix generated
10864 
10865   Level: developer
10866 
10867   Note:
10868   The number of columns of the matrix in EACH processor MUST be the same.
10869 
10870 .seealso: [](ch_matrices), `Mat`
10871 @*/
10872 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10873 {
10874   PetscMPIInt size;
10875 
10876   PetscFunctionBegin;
10877   PetscCallMPI(MPI_Comm_size(comm, &size));
10878   if (size == 1) {
10879     if (reuse == MAT_INITIAL_MATRIX) {
10880       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10881     } else {
10882       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10883     }
10884     PetscFunctionReturn(PETSC_SUCCESS);
10885   }
10886 
10887   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");
10888 
10889   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10890   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10891   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10892   PetscFunctionReturn(PETSC_SUCCESS);
10893 }
10894 
10895 /*@
10896   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10897 
10898   Collective
10899 
10900   Input Parameters:
10901 + A - the matrix to create subdomains from
10902 - N - requested number of subdomains
10903 
10904   Output Parameters:
10905 + n   - number of subdomains resulting on this MPI process
10906 - iss - `IS` list with indices of subdomains on this MPI process
10907 
10908   Level: advanced
10909 
10910   Note:
10911   The number of subdomains must be smaller than the communicator size
10912 
10913 .seealso: [](ch_matrices), `Mat`, `IS`
10914 @*/
10915 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10916 {
10917   MPI_Comm    comm, subcomm;
10918   PetscMPIInt size, rank, color;
10919   PetscInt    rstart, rend, k;
10920 
10921   PetscFunctionBegin;
10922   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10923   PetscCallMPI(MPI_Comm_size(comm, &size));
10924   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10925   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);
10926   *n    = 1;
10927   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10928   color = rank / k;
10929   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10930   PetscCall(PetscMalloc1(1, iss));
10931   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10932   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10933   PetscCallMPI(MPI_Comm_free(&subcomm));
10934   PetscFunctionReturn(PETSC_SUCCESS);
10935 }
10936 
10937 /*@
10938   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10939 
10940   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10941   If they are not the same, uses `MatMatMatMult()`.
10942 
10943   Once the coarse grid problem is constructed, correct for interpolation operators
10944   that are not of full rank, which can legitimately happen in the case of non-nested
10945   geometric multigrid.
10946 
10947   Input Parameters:
10948 + restrct     - restriction operator
10949 . dA          - fine grid matrix
10950 . interpolate - interpolation operator
10951 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10952 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10953 
10954   Output Parameter:
10955 . A - the Galerkin coarse matrix
10956 
10957   Options Database Key:
10958 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10959 
10960   Level: developer
10961 
10962 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10963 @*/
10964 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10965 {
10966   IS  zerorows;
10967   Vec diag;
10968 
10969   PetscFunctionBegin;
10970   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10971   /* Construct the coarse grid matrix */
10972   if (interpolate == restrct) {
10973     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10974   } else {
10975     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10976   }
10977 
10978   /* If the interpolation matrix is not of full rank, A will have zero rows.
10979      This can legitimately happen in the case of non-nested geometric multigrid.
10980      In that event, we set the rows of the matrix to the rows of the identity,
10981      ignoring the equations (as the RHS will also be zero). */
10982 
10983   PetscCall(MatFindZeroRows(*A, &zerorows));
10984 
10985   if (zerorows != NULL) { /* if there are any zero rows */
10986     PetscCall(MatCreateVecs(*A, &diag, NULL));
10987     PetscCall(MatGetDiagonal(*A, diag));
10988     PetscCall(VecISSet(diag, zerorows, 1.0));
10989     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10990     PetscCall(VecDestroy(&diag));
10991     PetscCall(ISDestroy(&zerorows));
10992   }
10993   PetscFunctionReturn(PETSC_SUCCESS);
10994 }
10995 
10996 /*@C
10997   MatSetOperation - Allows user to set a matrix operation for any matrix type
10998 
10999   Logically Collective
11000 
11001   Input Parameters:
11002 + mat - the matrix
11003 . op  - the name of the operation
11004 - f   - the function that provides the operation
11005 
11006   Level: developer
11007 
11008   Example Usage:
11009 .vb
11010   extern PetscErrorCode usermult(Mat, Vec, Vec);
11011 
11012   PetscCall(MatCreateXXX(comm, ..., &A));
11013   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11014 .ve
11015 
11016   Notes:
11017   See the file `include/petscmat.h` for a complete list of matrix
11018   operations, which all have the form MATOP_<OPERATION>, where
11019   <OPERATION> is the name (in all capital letters) of the
11020   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11021 
11022   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11023   sequence as the usual matrix interface routines, since they
11024   are intended to be accessed via the usual matrix interface
11025   routines, e.g.,
11026 .vb
11027   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11028 .ve
11029 
11030   In particular each function MUST return `PETSC_SUCCESS` on success and
11031   nonzero on failure.
11032 
11033   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11034 
11035 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11036 @*/
11037 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11038 {
11039   PetscFunctionBegin;
11040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11041   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11042   (((void (**)(void))mat->ops)[op]) = f;
11043   PetscFunctionReturn(PETSC_SUCCESS);
11044 }
11045 
11046 /*@C
11047   MatGetOperation - Gets a matrix operation for any matrix type.
11048 
11049   Not Collective
11050 
11051   Input Parameters:
11052 + mat - the matrix
11053 - op  - the name of the operation
11054 
11055   Output Parameter:
11056 . f - the function that provides the operation
11057 
11058   Level: developer
11059 
11060   Example Usage:
11061 .vb
11062   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11063 
11064   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11065 .ve
11066 
11067   Notes:
11068   See the file include/petscmat.h for a complete list of matrix
11069   operations, which all have the form MATOP_<OPERATION>, where
11070   <OPERATION> is the name (in all capital letters) of the
11071   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11072 
11073   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11074 
11075 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11076 @*/
11077 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11078 {
11079   PetscFunctionBegin;
11080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11081   *f = (((void (**)(void))mat->ops)[op]);
11082   PetscFunctionReturn(PETSC_SUCCESS);
11083 }
11084 
11085 /*@
11086   MatHasOperation - Determines whether the given matrix supports the particular operation.
11087 
11088   Not Collective
11089 
11090   Input Parameters:
11091 + mat - the matrix
11092 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11093 
11094   Output Parameter:
11095 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11096 
11097   Level: advanced
11098 
11099   Note:
11100   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11101 
11102 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11103 @*/
11104 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11105 {
11106   PetscFunctionBegin;
11107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11108   PetscAssertPointer(has, 3);
11109   if (mat->ops->hasoperation) {
11110     PetscUseTypeMethod(mat, hasoperation, op, has);
11111   } else {
11112     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11113     else {
11114       *has = PETSC_FALSE;
11115       if (op == MATOP_CREATE_SUBMATRIX) {
11116         PetscMPIInt size;
11117 
11118         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11119         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11120       }
11121     }
11122   }
11123   PetscFunctionReturn(PETSC_SUCCESS);
11124 }
11125 
11126 /*@
11127   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11128 
11129   Collective
11130 
11131   Input Parameter:
11132 . mat - the matrix
11133 
11134   Output Parameter:
11135 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11136 
11137   Level: beginner
11138 
11139 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11140 @*/
11141 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11142 {
11143   PetscFunctionBegin;
11144   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11145   PetscValidType(mat, 1);
11146   PetscAssertPointer(cong, 2);
11147   if (!mat->rmap || !mat->cmap) {
11148     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11149     PetscFunctionReturn(PETSC_SUCCESS);
11150   }
11151   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11152     PetscCall(PetscLayoutSetUp(mat->rmap));
11153     PetscCall(PetscLayoutSetUp(mat->cmap));
11154     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11155     if (*cong) mat->congruentlayouts = 1;
11156     else mat->congruentlayouts = 0;
11157   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11158   PetscFunctionReturn(PETSC_SUCCESS);
11159 }
11160 
11161 PetscErrorCode MatSetInf(Mat A)
11162 {
11163   PetscFunctionBegin;
11164   PetscUseTypeMethod(A, setinf);
11165   PetscFunctionReturn(PETSC_SUCCESS);
11166 }
11167 
11168 /*@C
11169   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
11170   and possibly removes small values from the graph structure.
11171 
11172   Collective
11173 
11174   Input Parameters:
11175 + A      - the matrix
11176 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11177 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11178 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11179 
11180   Output Parameter:
11181 . graph - the resulting graph
11182 
11183   Level: advanced
11184 
11185 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11186 @*/
11187 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11188 {
11189   PetscFunctionBegin;
11190   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11191   PetscValidType(A, 1);
11192   PetscValidLogicalCollectiveBool(A, scale, 3);
11193   PetscAssertPointer(graph, 5);
11194   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11195   PetscFunctionReturn(PETSC_SUCCESS);
11196 }
11197 
11198 /*@
11199   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11200   meaning the same memory is used for the matrix, and no new memory is allocated.
11201 
11202   Collective
11203 
11204   Input Parameters:
11205 + A    - the matrix
11206 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well
11207 
11208   Level: intermediate
11209 
11210   Developer Notes:
11211   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11212   of the arrays in the data structure are unneeded.
11213 
11214 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11215 @*/
11216 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11217 {
11218   PetscFunctionBegin;
11219   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11220   PetscUseTypeMethod(A, eliminatezeros, keep);
11221   PetscFunctionReturn(PETSC_SUCCESS);
11222 }
11223