xref: /petsc/src/mat/interface/matrix.c (revision b1fc5afd5246547405c8fcef1b22ffa75ad76260)
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_CreateGraph;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52   MatSetRandom - Sets all components of a matrix to random numbers.
53 
54   Logically Collective
55 
56   Input Parameters:
57 + x    - the matrix
58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61   Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68   Level: intermediate
69 
70   Notes:
71   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
72 
73   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
74 
75   It generates an error if used on unassembled sparse matrices that have not been preallocated.
76 
77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108   MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type
109 
110   Logically Collective
111 
112   Input Parameter:
113 . A - A matrix in unassembled, hash table form
114 
115   Output Parameter:
116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()`
117 
118   Example:
119 .vb
120      PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
121      PetscCall(MatCopyHashToXAIJ(A, B));
122 .ve
123 
124   Level: advanced
125 
126   Notes:
127   If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled
128 
129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE`
130 @*/
131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
135   PetscUseTypeMethod(A, copyhashtoxaij, B);
136   PetscFunctionReturn(PETSC_SUCCESS);
137 }
138 
139 /*@
140   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
141 
142   Logically Collective
143 
144   Input Parameter:
145 . mat - the factored matrix
146 
147   Output Parameters:
148 + pivot - the pivot value computed
149 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
150          the share the matrix
151 
152   Level: advanced
153 
154   Notes:
155   This routine does not work for factorizations done with external packages.
156 
157   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
158 
159   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
160 
161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
163 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
164 @*/
165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
166 {
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
169   PetscAssertPointer(pivot, 2);
170   PetscAssertPointer(row, 3);
171   *pivot = mat->factorerror_zeropivot_value;
172   *row   = mat->factorerror_zeropivot_row;
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@
177   MatFactorGetError - gets the error code from a factorization
178 
179   Logically Collective
180 
181   Input Parameter:
182 . mat - the factored matrix
183 
184   Output Parameter:
185 . err - the error code
186 
187   Level: advanced
188 
189   Note:
190   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
191 
192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
193           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
194 @*/
195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
196 {
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
199   PetscAssertPointer(err, 2);
200   *err = mat->factorerrortype;
201   PetscFunctionReturn(PETSC_SUCCESS);
202 }
203 
204 /*@
205   MatFactorClearError - clears the error code in a factorization
206 
207   Logically Collective
208 
209   Input Parameter:
210 . mat - the factored matrix
211 
212   Level: developer
213 
214   Note:
215   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
216 
217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
218           `MatGetErrorCode()`, `MatFactorError`
219 @*/
220 PetscErrorCode MatFactorClearError(Mat mat)
221 {
222   PetscFunctionBegin;
223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
224   mat->factorerrortype             = MAT_FACTOR_NOERROR;
225   mat->factorerror_zeropivot_value = 0.0;
226   mat->factorerror_zeropivot_row   = 0;
227   PetscFunctionReturn(PETSC_SUCCESS);
228 }
229 
230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
231 {
232   Vec                r, l;
233   const PetscScalar *al;
234   PetscInt           i, nz, gnz, N, n, st;
235 
236   PetscFunctionBegin;
237   PetscCall(MatCreateVecs(mat, &r, &l));
238   if (!cols) { /* nonzero rows */
239     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
240     PetscCall(MatGetSize(mat, &N, NULL));
241     PetscCall(MatGetLocalSize(mat, &n, NULL));
242     PetscCall(VecSet(l, 0.0));
243     PetscCall(VecSetRandom(r, NULL));
244     PetscCall(MatMult(mat, r, l));
245     PetscCall(VecGetArrayRead(l, &al));
246   } else { /* nonzero columns */
247     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
248     PetscCall(MatGetSize(mat, NULL, &N));
249     PetscCall(MatGetLocalSize(mat, NULL, &n));
250     PetscCall(VecSet(r, 0.0));
251     PetscCall(VecSetRandom(l, NULL));
252     PetscCall(MatMultTranspose(mat, l, r));
253     PetscCall(VecGetArrayRead(r, &al));
254   }
255   if (tol <= 0.0) {
256     for (i = 0, nz = 0; i < n; i++)
257       if (al[i] != 0.0) nz++;
258   } else {
259     for (i = 0, nz = 0; i < n; i++)
260       if (PetscAbsScalar(al[i]) > tol) nz++;
261   }
262   PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
263   if (gnz != N) {
264     PetscInt *nzr;
265     PetscCall(PetscMalloc1(nz, &nzr));
266     if (nz) {
267       if (tol < 0) {
268         for (i = 0, nz = 0; i < n; i++)
269           if (al[i] != 0.0) nzr[nz++] = i + st;
270       } else {
271         for (i = 0, nz = 0; i < n; i++)
272           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
273       }
274     }
275     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
276   } else *nonzero = NULL;
277   if (!cols) { /* nonzero rows */
278     PetscCall(VecRestoreArrayRead(l, &al));
279   } else {
280     PetscCall(VecRestoreArrayRead(r, &al));
281   }
282   PetscCall(VecDestroy(&l));
283   PetscCall(VecDestroy(&r));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
289 
290   Input Parameter:
291 . mat - the matrix
292 
293   Output Parameter:
294 . keptrows - the rows that are not completely zero
295 
296   Level: intermediate
297 
298   Note:
299   `keptrows` is set to `NULL` if all rows are nonzero.
300 
301   Developer Note:
302   If `keptrows` is not `NULL`, it must be sorted.
303 
304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
305  @*/
306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
307 {
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310   PetscValidType(mat, 1);
311   PetscAssertPointer(keptrows, 2);
312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
314   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
315   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
316   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatFindZeroRows - Locate all rows that are completely zero in the matrix
322 
323   Input Parameter:
324 . mat - the matrix
325 
326   Output Parameter:
327 . zerorows - the rows that are completely zero
328 
329   Level: intermediate
330 
331   Note:
332   `zerorows` is set to `NULL` if no rows are zero.
333 
334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
335  @*/
336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
337 {
338   IS       keptrows;
339   PetscInt m, n;
340 
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
343   PetscValidType(mat, 1);
344   PetscAssertPointer(zerorows, 2);
345   PetscCall(MatFindNonzeroRows(mat, &keptrows));
346   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
347      In keeping with this convention, we set zerorows to NULL if there are no zero
348      rows. */
349   if (keptrows == NULL) {
350     *zerorows = NULL;
351   } else {
352     PetscCall(MatGetOwnershipRange(mat, &m, &n));
353     PetscCall(ISComplement(keptrows, m, n, zerorows));
354     PetscCall(ISDestroy(&keptrows));
355   }
356   PetscFunctionReturn(PETSC_SUCCESS);
357 }
358 
359 /*@
360   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
361 
362   Not Collective
363 
364   Input Parameter:
365 . A - the matrix
366 
367   Output Parameter:
368 . a - the diagonal part (which is a SEQUENTIAL matrix)
369 
370   Level: advanced
371 
372   Notes:
373   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
374 
375   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
376 
377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
378 @*/
379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
380 {
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
383   PetscValidType(A, 1);
384   PetscAssertPointer(a, 2);
385   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
386   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
387   else {
388     PetscMPIInt size;
389 
390     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
391     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
392     *a = A;
393   }
394   PetscFunctionReturn(PETSC_SUCCESS);
395 }
396 
397 /*@
398   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
399 
400   Collective
401 
402   Input Parameter:
403 . mat - the matrix
404 
405   Output Parameter:
406 . trace - the sum of the diagonal entries
407 
408   Level: advanced
409 
410 .seealso: [](ch_matrices), `Mat`
411 @*/
412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
413 {
414   Vec diag;
415 
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
418   PetscAssertPointer(trace, 2);
419   PetscCall(MatCreateVecs(mat, &diag, NULL));
420   PetscCall(MatGetDiagonal(mat, diag));
421   PetscCall(VecSum(diag, trace));
422   PetscCall(VecDestroy(&diag));
423   PetscFunctionReturn(PETSC_SUCCESS);
424 }
425 
426 /*@
427   MatRealPart - Zeros out the imaginary part of the matrix
428 
429   Logically Collective
430 
431   Input Parameter:
432 . mat - the matrix
433 
434   Level: advanced
435 
436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
437 @*/
438 PetscErrorCode MatRealPart(Mat mat)
439 {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442   PetscValidType(mat, 1);
443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445   MatCheckPreallocated(mat, 1);
446   PetscUseTypeMethod(mat, realpart);
447   PetscFunctionReturn(PETSC_SUCCESS);
448 }
449 
450 /*@C
451   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
452 
453   Collective
454 
455   Input Parameter:
456 . mat - the matrix
457 
458   Output Parameters:
459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
460 - ghosts  - the global indices of the ghost points
461 
462   Level: advanced
463 
464   Note:
465   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
466 
467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
468 @*/
469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
470 {
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
473   PetscValidType(mat, 1);
474   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
475   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
476   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
477   else {
478     if (nghosts) *nghosts = 0;
479     if (ghosts) *ghosts = NULL;
480   }
481   PetscFunctionReturn(PETSC_SUCCESS);
482 }
483 
484 /*@
485   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
486 
487   Logically Collective
488 
489   Input Parameter:
490 . mat - the matrix
491 
492   Level: advanced
493 
494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
495 @*/
496 PetscErrorCode MatImaginaryPart(Mat mat)
497 {
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
500   PetscValidType(mat, 1);
501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
503   MatCheckPreallocated(mat, 1);
504   PetscUseTypeMethod(mat, imaginarypart);
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 
508 /*@
509   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
510 
511   Not Collective
512 
513   Input Parameter:
514 . mat - the matrix
515 
516   Output Parameters:
517 + missing - is any diagonal entry missing
518 - dd      - first diagonal entry that is missing (optional) on this process
519 
520   Level: advanced
521 
522   Note:
523   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
524 
525 .seealso: [](ch_matrices), `Mat`
526 @*/
527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
528 {
529   PetscFunctionBegin;
530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
531   PetscValidType(mat, 1);
532   PetscAssertPointer(missing, 2);
533   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
534   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
535   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
540 /*@C
541   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
542   for each row that you get to ensure that your application does
543   not bleed memory.
544 
545   Not Collective
546 
547   Input Parameters:
548 + mat - the matrix
549 - row - the row to get
550 
551   Output Parameters:
552 + ncols - if not `NULL`, the number of nonzeros in `row`
553 . cols  - if not `NULL`, the column numbers
554 - vals  - if not `NULL`, the numerical values
555 
556   Level: advanced
557 
558   Notes:
559   This routine is provided for people who need to have direct access
560   to the structure of a matrix.  We hope that we provide enough
561   high-level matrix routines that few users will need it.
562 
563   `MatGetRow()` always returns 0-based column indices, regardless of
564   whether the internal representation is 0-based (default) or 1-based.
565 
566   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
567   not wish to extract these quantities.
568 
569   The user can only examine the values extracted with `MatGetRow()`;
570   the values CANNOT be altered.  To change the matrix entries, one
571   must use `MatSetValues()`.
572 
573   You can only have one call to `MatGetRow()` outstanding for a particular
574   matrix at a time, per processor. `MatGetRow()` can only obtain rows
575   associated with the given processor, it cannot get rows from the
576   other processors; for that we suggest using `MatCreateSubMatrices()`, then
577   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
578   is in the global number of rows.
579 
580   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
581 
582   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
583 
584   Fortran Note:
585 .vb
586   PetscInt, pointer :: cols(:)
587   PetscScalar, pointer :: vals(:)
588 .ve
589 
590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
591 @*/
592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
593 {
594   PetscInt incols;
595 
596   PetscFunctionBegin;
597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
598   PetscValidType(mat, 1);
599   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
600   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
601   MatCheckPreallocated(mat, 1);
602   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);
603   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
604   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
605   if (ncols) *ncols = incols;
606   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
607   PetscFunctionReturn(PETSC_SUCCESS);
608 }
609 
610 /*@
611   MatConjugate - replaces the matrix values with their complex conjugates
612 
613   Logically Collective
614 
615   Input Parameter:
616 . mat - the matrix
617 
618   Level: advanced
619 
620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
621 @*/
622 PetscErrorCode MatConjugate(Mat mat)
623 {
624   PetscFunctionBegin;
625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
627   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
628     PetscUseTypeMethod(mat, conjugate);
629     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
630   }
631   PetscFunctionReturn(PETSC_SUCCESS);
632 }
633 
634 /*@C
635   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
636 
637   Not Collective
638 
639   Input Parameters:
640 + mat   - the matrix
641 . row   - the row to get
642 . ncols - the number of nonzeros
643 . cols  - the columns of the nonzeros
644 - vals  - if nonzero the column values
645 
646   Level: advanced
647 
648   Notes:
649   This routine should be called after you have finished examining the entries.
650 
651   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
652   us of the array after it has been restored. If you pass `NULL`, it will
653   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
654 
655   Fortran Note:
656 .vb
657   PetscInt, pointer :: cols(:)
658   PetscScalar, pointer :: vals(:)
659 .ve
660 
661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
662 @*/
663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
664 {
665   PetscFunctionBegin;
666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
667   if (ncols) PetscAssertPointer(ncols, 3);
668   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
669   PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
670   if (ncols) *ncols = 0;
671   if (cols) *cols = NULL;
672   if (vals) *vals = NULL;
673   PetscFunctionReturn(PETSC_SUCCESS);
674 }
675 
676 /*@
677   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
678   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
679 
680   Not Collective
681 
682   Input Parameter:
683 . mat - the matrix
684 
685   Level: advanced
686 
687   Note:
688   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.
689 
690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   PetscTryTypeMethod(mat, getrowuppertriangular);
701   PetscFunctionReturn(PETSC_SUCCESS);
702 }
703 
704 /*@
705   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
706 
707   Not Collective
708 
709   Input Parameter:
710 . mat - the matrix
711 
712   Level: advanced
713 
714   Note:
715   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
716 
717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
718 @*/
719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
720 {
721   PetscFunctionBegin;
722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
723   PetscValidType(mat, 1);
724   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
725   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
726   MatCheckPreallocated(mat, 1);
727   PetscTryTypeMethod(mat, restorerowuppertriangular);
728   PetscFunctionReturn(PETSC_SUCCESS);
729 }
730 
731 /*@
732   MatSetOptionsPrefix - Sets the prefix used for searching for all
733   `Mat` options in the database.
734 
735   Logically Collective
736 
737   Input Parameters:
738 + A      - the matrix
739 - prefix - the prefix to prepend to all option names
740 
741   Level: advanced
742 
743   Notes:
744   A hyphen (-) must NOT be given at the beginning of the prefix name.
745   The first character of all runtime options is AUTOMATICALLY the hyphen.
746 
747   This is NOT used for options for the factorization of the matrix. Normally the
748   prefix is automatically passed in from the PC calling the factorization. To set
749   it directly use  `MatSetOptionsPrefixFactor()`
750 
751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
752 @*/
753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
754 {
755   PetscFunctionBegin;
756   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
757   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
758   PetscFunctionReturn(PETSC_SUCCESS);
759 }
760 
761 /*@
762   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
763   for matrices created with `MatGetFactor()`
764 
765   Logically Collective
766 
767   Input Parameters:
768 + A      - the matrix
769 - prefix - the prefix to prepend to all option names for the factored matrix
770 
771   Level: developer
772 
773   Notes:
774   A hyphen (-) must NOT be given at the beginning of the prefix name.
775   The first character of all runtime options is AUTOMATICALLY the hyphen.
776 
777   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
778   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
779 
780 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
781 @*/
782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
783 {
784   PetscFunctionBegin;
785   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
786   if (prefix) {
787     PetscAssertPointer(prefix, 2);
788     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
789     if (prefix != A->factorprefix) {
790       PetscCall(PetscFree(A->factorprefix));
791       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
792     }
793   } else PetscCall(PetscFree(A->factorprefix));
794   PetscFunctionReturn(PETSC_SUCCESS);
795 }
796 
797 /*@
798   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
799   for matrices created with `MatGetFactor()`
800 
801   Logically Collective
802 
803   Input Parameters:
804 + A      - the matrix
805 - prefix - the prefix to prepend to all option names for the factored matrix
806 
807   Level: developer
808 
809   Notes:
810   A hyphen (-) must NOT be given at the beginning of the prefix name.
811   The first character of all runtime options is AUTOMATICALLY the hyphen.
812 
813   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
814   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
815 
816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
817           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
818           `MatSetOptionsPrefix()`
819 @*/
820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
821 {
822   size_t len1, len2, new_len;
823 
824   PetscFunctionBegin;
825   PetscValidHeader(A, 1);
826   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
827   if (!A->factorprefix) {
828     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
829     PetscFunctionReturn(PETSC_SUCCESS);
830   }
831   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
832 
833   PetscCall(PetscStrlen(A->factorprefix, &len1));
834   PetscCall(PetscStrlen(prefix, &len2));
835   new_len = len1 + len2 + 1;
836   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
837   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
838   PetscFunctionReturn(PETSC_SUCCESS);
839 }
840 
841 /*@
842   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
843   matrix options in the database.
844 
845   Logically Collective
846 
847   Input Parameters:
848 + A      - the matrix
849 - prefix - the prefix to prepend to all option names
850 
851   Level: advanced
852 
853   Note:
854   A hyphen (-) must NOT be given at the beginning of the prefix name.
855   The first character of all runtime options is AUTOMATICALLY the hyphen.
856 
857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
858 @*/
859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
860 {
861   PetscFunctionBegin;
862   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
863   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
864   PetscFunctionReturn(PETSC_SUCCESS);
865 }
866 
867 /*@
868   MatGetOptionsPrefix - Gets the prefix used for searching for all
869   matrix options in the database.
870 
871   Not Collective
872 
873   Input Parameter:
874 . A - the matrix
875 
876   Output Parameter:
877 . prefix - pointer to the prefix string used
878 
879   Level: advanced
880 
881 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
882 @*/
883 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
884 {
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
887   PetscAssertPointer(prefix, 2);
888   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
889   PetscFunctionReturn(PETSC_SUCCESS);
890 }
891 
892 /*@
893   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
894 
895   Not Collective
896 
897   Input Parameter:
898 . A - the matrix
899 
900   Output Parameter:
901 . state - the object state
902 
903   Level: advanced
904 
905   Note:
906   Object state is an integer which gets increased every time
907   the object is changed. By saving and later querying the object state
908   one can determine whether information about the object is still current.
909 
910   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
911 
912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
913 @*/
914 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
915 {
916   PetscFunctionBegin;
917   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
918   PetscAssertPointer(state, 2);
919   PetscCall(PetscObjectStateGet((PetscObject)A, state));
920   PetscFunctionReturn(PETSC_SUCCESS);
921 }
922 
923 /*@
924   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
925 
926   Collective
927 
928   Input Parameter:
929 . A - the matrix
930 
931   Level: beginner
932 
933   Notes:
934   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
935   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
936   makes all of the preallocation space available
937 
938   Current values in the matrix are lost in this call
939 
940   Currently only supported for  `MATAIJ` matrices.
941 
942 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
943 @*/
944 PetscErrorCode MatResetPreallocation(Mat A)
945 {
946   PetscFunctionBegin;
947   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
948   PetscValidType(A, 1);
949   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
950   PetscFunctionReturn(PETSC_SUCCESS);
951 }
952 
953 /*@
954   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
955 
956   Collective
957 
958   Input Parameter:
959 . A - the matrix
960 
961   Level: intermediate
962 
963   Notes:
964   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
965 
966   Currently only supported for `MATAIJ` matrices.
967 
968 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
969 @*/
970 PetscErrorCode MatResetHash(Mat A)
971 {
972   PetscFunctionBegin;
973   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
974   PetscValidType(A, 1);
975   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
976   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
977   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
978   /* These flags are used to determine whether certain setups occur */
979   A->was_assembled = PETSC_FALSE;
980   A->assembled     = PETSC_FALSE;
981   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
982   PetscCall(PetscObjectStateIncrease((PetscObject)A));
983   PetscFunctionReturn(PETSC_SUCCESS);
984 }
985 
986 /*@
987   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
988 
989   Collective
990 
991   Input Parameter:
992 . A - the matrix
993 
994   Level: advanced
995 
996   Notes:
997   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
998   setting values in the matrix.
999 
1000   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1001 
1002 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1003 @*/
1004 PetscErrorCode MatSetUp(Mat A)
1005 {
1006   PetscFunctionBegin;
1007   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1008   if (!((PetscObject)A)->type_name) {
1009     PetscMPIInt size;
1010 
1011     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1012     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1013   }
1014   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1015   PetscCall(PetscLayoutSetUp(A->rmap));
1016   PetscCall(PetscLayoutSetUp(A->cmap));
1017   A->preallocated = PETSC_TRUE;
1018   PetscFunctionReturn(PETSC_SUCCESS);
1019 }
1020 
1021 #if defined(PETSC_HAVE_SAWS)
1022   #include <petscviewersaws.h>
1023 #endif
1024 
1025 /*
1026    If threadsafety is on extraneous matrices may be printed
1027 
1028    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1029 */
1030 #if !defined(PETSC_HAVE_THREADSAFETY)
1031 static PetscInt insidematview = 0;
1032 #endif
1033 
1034 /*@
1035   MatViewFromOptions - View properties of the matrix based on options set in the options database
1036 
1037   Collective
1038 
1039   Input Parameters:
1040 + A    - the matrix
1041 . obj  - optional additional object that provides the options prefix to use
1042 - name - command line option
1043 
1044   Options Database Key:
1045 . -mat_view [viewertype]:... - the viewer and its options
1046 
1047   Level: intermediate
1048 
1049   Note:
1050 .vb
1051     If no value is provided ascii:stdout is used
1052        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1053                                                   for example ascii::ascii_info prints just the information about the object not all details
1054                                                   unless :append is given filename opens in write mode, overwriting what was already there
1055        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1056        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1057        socket[:port]                             defaults to the standard output port
1058        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1059 .ve
1060 
1061 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1062 @*/
1063 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1064 {
1065   PetscFunctionBegin;
1066   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1067 #if !defined(PETSC_HAVE_THREADSAFETY)
1068   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1069 #endif
1070   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1071   PetscFunctionReturn(PETSC_SUCCESS);
1072 }
1073 
1074 /*@
1075   MatView - display information about a matrix in a variety ways
1076 
1077   Collective on viewer
1078 
1079   Input Parameters:
1080 + mat    - the matrix
1081 - viewer - visualization context
1082 
1083   Options Database Keys:
1084 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1085 . -mat_view ::ascii_info_detail    - Prints more detailed info
1086 . -mat_view                        - Prints matrix in ASCII format
1087 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1088 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1089 . -display <name>                  - Sets display name (default is host)
1090 . -draw_pause <sec>                - Sets number of seconds to pause after display
1091 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1092 . -viewer_socket_machine <machine> - -
1093 . -viewer_socket_port <port>       - -
1094 . -mat_view binary                 - save matrix to file in binary format
1095 - -viewer_binary_filename <name>   - -
1096 
1097   Level: beginner
1098 
1099   Notes:
1100   The available visualization contexts include
1101 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1102 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1103 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1104 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1105 
1106   The user can open alternative visualization contexts with
1107 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1108 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1109 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1110 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1111 
1112   The user can call `PetscViewerPushFormat()` to specify the output
1113   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1114   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1115 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1116 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1117 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1118 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1119 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1120 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1121 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1122 
1123   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1124   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1125 
1126   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1127 
1128   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1129   viewer is used.
1130 
1131   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1132   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1133 
1134   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1135   and then use the following mouse functions.
1136 .vb
1137   left mouse: zoom in
1138   middle mouse: zoom out
1139   right mouse: continue with the simulation
1140 .ve
1141 
1142 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1143           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1144 @*/
1145 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1146 {
1147   PetscInt          rows, cols, rbs, cbs;
1148   PetscBool         isascii, isstring, issaws;
1149   PetscViewerFormat format;
1150   PetscMPIInt       size;
1151 
1152   PetscFunctionBegin;
1153   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1154   PetscValidType(mat, 1);
1155   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1156   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1157 
1158   PetscCall(PetscViewerGetFormat(viewer, &format));
1159   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1160   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1161 
1162 #if !defined(PETSC_HAVE_THREADSAFETY)
1163   insidematview++;
1164 #endif
1165   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1166   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1167   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1168   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1169 
1170   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1171   if (isascii) {
1172     if (!mat->preallocated) {
1173       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1174 #if !defined(PETSC_HAVE_THREADSAFETY)
1175       insidematview--;
1176 #endif
1177       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1178       PetscFunctionReturn(PETSC_SUCCESS);
1179     }
1180     if (!mat->assembled) {
1181       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1182 #if !defined(PETSC_HAVE_THREADSAFETY)
1183       insidematview--;
1184 #endif
1185       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1186       PetscFunctionReturn(PETSC_SUCCESS);
1187     }
1188     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1189     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1190       MatNullSpace nullsp, transnullsp;
1191 
1192       PetscCall(PetscViewerASCIIPushTab(viewer));
1193       PetscCall(MatGetSize(mat, &rows, &cols));
1194       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1195       if (rbs != 1 || cbs != 1) {
1196         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : ""));
1197         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1198       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1199       if (mat->factortype) {
1200         MatSolverType solver;
1201         PetscCall(MatFactorGetSolverType(mat, &solver));
1202         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1203       }
1204       if (mat->ops->getinfo) {
1205         MatInfo info;
1206         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1207         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1208         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1209       }
1210       PetscCall(MatGetNullSpace(mat, &nullsp));
1211       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1212       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1213       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1214       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1215       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1216       PetscCall(PetscViewerASCIIPushTab(viewer));
1217       PetscCall(MatProductView(mat, viewer));
1218       PetscCall(PetscViewerASCIIPopTab(viewer));
1219       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1220         IS tmp;
1221 
1222         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1223         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1224         PetscCall(PetscViewerASCIIPushTab(viewer));
1225         PetscCall(ISView(tmp, viewer));
1226         PetscCall(PetscViewerASCIIPopTab(viewer));
1227         PetscCall(ISDestroy(&tmp));
1228       }
1229     }
1230   } else if (issaws) {
1231 #if defined(PETSC_HAVE_SAWS)
1232     PetscMPIInt rank;
1233 
1234     PetscCall(PetscObjectName((PetscObject)mat));
1235     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1236     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1237 #endif
1238   } else if (isstring) {
1239     const char *type;
1240     PetscCall(MatGetType(mat, &type));
1241     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1242     PetscTryTypeMethod(mat, view, viewer);
1243   }
1244   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1245     PetscCall(PetscViewerASCIIPushTab(viewer));
1246     PetscUseTypeMethod(mat, viewnative, viewer);
1247     PetscCall(PetscViewerASCIIPopTab(viewer));
1248   } else if (mat->ops->view) {
1249     PetscCall(PetscViewerASCIIPushTab(viewer));
1250     PetscUseTypeMethod(mat, view, viewer);
1251     PetscCall(PetscViewerASCIIPopTab(viewer));
1252   }
1253   if (isascii) {
1254     PetscCall(PetscViewerGetFormat(viewer, &format));
1255     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1256   }
1257   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1258 #if !defined(PETSC_HAVE_THREADSAFETY)
1259   insidematview--;
1260 #endif
1261   PetscFunctionReturn(PETSC_SUCCESS);
1262 }
1263 
1264 #if defined(PETSC_USE_DEBUG)
1265   #include <../src/sys/totalview/tv_data_display.h>
1266 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1267 {
1268   TV_add_row("Local rows", "int", &mat->rmap->n);
1269   TV_add_row("Local columns", "int", &mat->cmap->n);
1270   TV_add_row("Global rows", "int", &mat->rmap->N);
1271   TV_add_row("Global columns", "int", &mat->cmap->N);
1272   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1273   return TV_format_OK;
1274 }
1275 #endif
1276 
1277 /*@
1278   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1279   with `MatView()`.  The matrix format is determined from the options database.
1280   Generates a parallel MPI matrix if the communicator has more than one
1281   processor.  The default matrix type is `MATAIJ`.
1282 
1283   Collective
1284 
1285   Input Parameters:
1286 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1287             or some related function before a call to `MatLoad()`
1288 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1289 
1290   Options Database Key:
1291 . -matload_block_size <bs> - set block size
1292 
1293   Level: beginner
1294 
1295   Notes:
1296   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1297   `Mat` before calling this routine if you wish to set it from the options database.
1298 
1299   `MatLoad()` automatically loads into the options database any options
1300   given in the file filename.info where filename is the name of the file
1301   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1302   file will be ignored if you use the -viewer_binary_skip_info option.
1303 
1304   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1305   sets the default matrix type AIJ and sets the local and global sizes.
1306   If type and/or size is already set, then the same are used.
1307 
1308   In parallel, each processor can load a subset of rows (or the
1309   entire matrix).  This routine is especially useful when a large
1310   matrix is stored on disk and only part of it is desired on each
1311   processor.  For example, a parallel solver may access only some of
1312   the rows from each processor.  The algorithm used here reads
1313   relatively small blocks of data rather than reading the entire
1314   matrix and then subsetting it.
1315 
1316   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1317   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1318   or the sequence like
1319 .vb
1320     `PetscViewer` v;
1321     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1322     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1323     `PetscViewerSetFromOptions`(v);
1324     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1325     `PetscViewerFileSetName`(v,"datafile");
1326 .ve
1327   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1328 .vb
1329   -viewer_type {binary, hdf5}
1330 .ve
1331 
1332   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1333   and src/mat/tutorials/ex10.c with the second approach.
1334 
1335   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1336   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1337   Multiple objects, both matrices and vectors, can be stored within the same file.
1338   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1339 
1340   Most users should not need to know the details of the binary storage
1341   format, since `MatLoad()` and `MatView()` completely hide these details.
1342   But for anyone who is interested, the standard binary matrix storage
1343   format is
1344 
1345 .vb
1346     PetscInt    MAT_FILE_CLASSID
1347     PetscInt    number of rows
1348     PetscInt    number of columns
1349     PetscInt    total number of nonzeros
1350     PetscInt    *number nonzeros in each row
1351     PetscInt    *column indices of all nonzeros (starting index is zero)
1352     PetscScalar *values of all nonzeros
1353 .ve
1354   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1355   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
1356   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1357 
1358   PETSc automatically does the byte swapping for
1359   machines that store the bytes reversed. Thus if you write your own binary
1360   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1361   and `PetscBinaryWrite()` to see how this may be done.
1362 
1363   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1364   Each processor's chunk is loaded independently by its owning MPI process.
1365   Multiple objects, both matrices and vectors, can be stored within the same file.
1366   They are looked up by their PetscObject name.
1367 
1368   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1369   by default the same structure and naming of the AIJ arrays and column count
1370   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1371 .vb
1372   save example.mat A b -v7.3
1373 .ve
1374   can be directly read by this routine (see Reference 1 for details).
1375 
1376   Depending on your MATLAB version, this format might be a default,
1377   otherwise you can set it as default in Preferences.
1378 
1379   Unless -nocompression flag is used to save the file in MATLAB,
1380   PETSc must be configured with ZLIB package.
1381 
1382   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1383 
1384   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1385 
1386   Corresponding `MatView()` is not yet implemented.
1387 
1388   The loaded matrix is actually a transpose of the original one in MATLAB,
1389   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1390   With this format, matrix is automatically transposed by PETSc,
1391   unless the matrix is marked as SPD or symmetric
1392   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1393 
1394   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1395 
1396 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1397  @*/
1398 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1399 {
1400   PetscBool flg;
1401 
1402   PetscFunctionBegin;
1403   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1404   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1405 
1406   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1407 
1408   flg = PETSC_FALSE;
1409   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1410   if (flg) {
1411     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1412     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1413   }
1414   flg = PETSC_FALSE;
1415   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1416   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1417 
1418   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1419   PetscUseTypeMethod(mat, load, viewer);
1420   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1421   PetscFunctionReturn(PETSC_SUCCESS);
1422 }
1423 
1424 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1425 {
1426   Mat_Redundant *redund = *redundant;
1427 
1428   PetscFunctionBegin;
1429   if (redund) {
1430     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1431       PetscCall(ISDestroy(&redund->isrow));
1432       PetscCall(ISDestroy(&redund->iscol));
1433       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1434     } else {
1435       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1436       PetscCall(PetscFree(redund->sbuf_j));
1437       PetscCall(PetscFree(redund->sbuf_a));
1438       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1439         PetscCall(PetscFree(redund->rbuf_j[i]));
1440         PetscCall(PetscFree(redund->rbuf_a[i]));
1441       }
1442       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1443     }
1444 
1445     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1446     PetscCall(PetscFree(redund));
1447   }
1448   PetscFunctionReturn(PETSC_SUCCESS);
1449 }
1450 
1451 /*@
1452   MatDestroy - Frees space taken by a matrix.
1453 
1454   Collective
1455 
1456   Input Parameter:
1457 . A - the matrix
1458 
1459   Level: beginner
1460 
1461   Developer Note:
1462   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1463   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1464   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1465   if changes are needed here.
1466 
1467 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1468 @*/
1469 PetscErrorCode MatDestroy(Mat *A)
1470 {
1471   PetscFunctionBegin;
1472   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1473   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1474   if (--((PetscObject)*A)->refct > 0) {
1475     *A = NULL;
1476     PetscFunctionReturn(PETSC_SUCCESS);
1477   }
1478 
1479   /* if memory was published with SAWs then destroy it */
1480   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1481   PetscTryTypeMethod(*A, destroy);
1482 
1483   PetscCall(PetscFree((*A)->factorprefix));
1484   PetscCall(PetscFree((*A)->defaultvectype));
1485   PetscCall(PetscFree((*A)->defaultrandtype));
1486   PetscCall(PetscFree((*A)->bsizes));
1487   PetscCall(PetscFree((*A)->solvertype));
1488   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1489   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1490   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1491   PetscCall(MatProductClear(*A));
1492   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1493   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1494   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1495   PetscCall(MatDestroy(&(*A)->schur));
1496   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1497   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1498   PetscCall(PetscHeaderDestroy(A));
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1503 /*@
1504   MatSetValues - Inserts or adds a block of values into a matrix.
1505   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1506   MUST be called after all calls to `MatSetValues()` have been completed.
1507 
1508   Not Collective
1509 
1510   Input Parameters:
1511 + mat  - the matrix
1512 . m    - the number of rows
1513 . idxm - the global indices of the rows
1514 . n    - the number of columns
1515 . idxn - the global indices of the columns
1516 . v    - a logically two-dimensional array of values
1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1523 
1524   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525   options cannot be mixed without intervening calls to the assembly
1526   routines.
1527 
1528   `MatSetValues()` uses 0-based row and column numbers in Fortran
1529   as well as in C.
1530 
1531   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1532   simply ignored. This allows easily inserting element stiffness matrices
1533   with homogeneous Dirichlet boundary conditions that you don't want represented
1534   in the matrix.
1535 
1536   Efficiency Alert:
1537   The routine `MatSetValuesBlocked()` may offer much better efficiency
1538   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540   Fortran Notes:
1541   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1542 .vb
1543   call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1544 .ve
1545 
1546   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1547 
1548   Developer Note:
1549   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1550   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1551 
1552 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1553           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1554 @*/
1555 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1556 {
1557   PetscFunctionBeginHot;
1558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1559   PetscValidType(mat, 1);
1560   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1561   PetscAssertPointer(idxm, 3);
1562   PetscAssertPointer(idxn, 5);
1563   MatCheckPreallocated(mat, 1);
1564 
1565   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1566   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1567 
1568   if (PetscDefined(USE_DEBUG)) {
1569     PetscInt i, j;
1570 
1571     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1572     if (v) {
1573       for (i = 0; i < m; i++) {
1574         for (j = 0; j < n; j++) {
1575           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1576 #if defined(PETSC_USE_COMPLEX)
1577             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]);
1578 #else
1579             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]);
1580 #endif
1581         }
1582       }
1583     }
1584     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);
1585     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);
1586   }
1587 
1588   if (mat->assembled) {
1589     mat->was_assembled = PETSC_TRUE;
1590     mat->assembled     = PETSC_FALSE;
1591   }
1592   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1593   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1594   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1595   PetscFunctionReturn(PETSC_SUCCESS);
1596 }
1597 
1598 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1599 /*@
1600   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1601   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1602   MUST be called after all calls to `MatSetValues()` have been completed.
1603 
1604   Not Collective
1605 
1606   Input Parameters:
1607 + mat  - the matrix
1608 . ism  - the rows to provide
1609 . isn  - the columns to provide
1610 . v    - a logically two-dimensional array of values
1611 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1612 
1613   Level: beginner
1614 
1615   Notes:
1616   By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
1617 
1618   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1619   options cannot be mixed without intervening calls to the assembly
1620   routines.
1621 
1622   `MatSetValues()` uses 0-based row and column numbers in Fortran
1623   as well as in C.
1624 
1625   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1626   simply ignored. This allows easily inserting element stiffness matrices
1627   with homogeneous Dirichlet boundary conditions that you don't want represented
1628   in the matrix.
1629 
1630   Efficiency Alert:
1631   The routine `MatSetValuesBlocked()` may offer much better efficiency
1632   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1633 
1634   This is currently not optimized for any particular `ISType`
1635 
1636 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1637           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1638 @*/
1639 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1640 {
1641   PetscInt        m, n;
1642   const PetscInt *rows, *cols;
1643 
1644   PetscFunctionBeginHot;
1645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1646   PetscCall(ISGetIndices(ism, &rows));
1647   PetscCall(ISGetIndices(isn, &cols));
1648   PetscCall(ISGetLocalSize(ism, &m));
1649   PetscCall(ISGetLocalSize(isn, &n));
1650   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1651   PetscCall(ISRestoreIndices(ism, &rows));
1652   PetscCall(ISRestoreIndices(isn, &cols));
1653   PetscFunctionReturn(PETSC_SUCCESS);
1654 }
1655 
1656 /*@
1657   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1658   values into a matrix
1659 
1660   Not Collective
1661 
1662   Input Parameters:
1663 + mat - the matrix
1664 . row - the (block) row to set
1665 - v   - a logically two-dimensional array of values
1666 
1667   Level: intermediate
1668 
1669   Notes:
1670   The values, `v`, are column-oriented (for the block version) and sorted
1671 
1672   All the nonzero values in `row` must be provided
1673 
1674   The matrix must have previously had its column indices set, likely by having been assembled.
1675 
1676   `row` must belong to this MPI process
1677 
1678 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1679           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1680 @*/
1681 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1682 {
1683   PetscInt globalrow;
1684 
1685   PetscFunctionBegin;
1686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1687   PetscValidType(mat, 1);
1688   PetscAssertPointer(v, 3);
1689   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1690   PetscCall(MatSetValuesRow(mat, globalrow, v));
1691   PetscFunctionReturn(PETSC_SUCCESS);
1692 }
1693 
1694 /*@
1695   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1696   values into a matrix
1697 
1698   Not Collective
1699 
1700   Input Parameters:
1701 + mat - the matrix
1702 . row - the (block) row to set
1703 - 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
1704 
1705   Level: advanced
1706 
1707   Notes:
1708   The values, `v`, are column-oriented for the block version.
1709 
1710   All the nonzeros in `row` must be provided
1711 
1712   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1713 
1714   `row` must belong to this process
1715 
1716 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1717           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1718 @*/
1719 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1720 {
1721   PetscFunctionBeginHot;
1722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1723   PetscValidType(mat, 1);
1724   MatCheckPreallocated(mat, 1);
1725   PetscAssertPointer(v, 3);
1726   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1727   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1728   mat->insertmode = INSERT_VALUES;
1729 
1730   if (mat->assembled) {
1731     mat->was_assembled = PETSC_TRUE;
1732     mat->assembled     = PETSC_FALSE;
1733   }
1734   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1735   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1736   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1737   PetscFunctionReturn(PETSC_SUCCESS);
1738 }
1739 
1740 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1741 /*@
1742   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1743   Using structured grid indexing
1744 
1745   Not Collective
1746 
1747   Input Parameters:
1748 + mat  - the matrix
1749 . m    - number of rows being entered
1750 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1751 . n    - number of columns being entered
1752 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1753 . v    - a logically two-dimensional array of values
1754 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1755 
1756   Level: beginner
1757 
1758   Notes:
1759   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1760 
1761   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1762   options cannot be mixed without intervening calls to the assembly
1763   routines.
1764 
1765   The grid coordinates are across the entire grid, not just the local portion
1766 
1767   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1768   as well as in C.
1769 
1770   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1771 
1772   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1773   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1774 
1775   The columns and rows in the stencil passed in MUST be contained within the
1776   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1777   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1778   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1779   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1780 
1781   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1782   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1783   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1784   `DM_BOUNDARY_PERIODIC` boundary type.
1785 
1786   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
1787   a single value per point) you can skip filling those indices.
1788 
1789   Inspired by the structured grid interface to the HYPRE package
1790   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1791 
1792   Efficiency Alert:
1793   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1794   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1795 
1796 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1798 @*/
1799 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscAssertPointer(idxm, 3);
1810   PetscAssertPointer(idxn, 5);
1811 
1812   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1813     jdxm = buf;
1814     jdxn = buf + m;
1815   } else {
1816     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1817     jdxm = bufm;
1818     jdxn = bufn;
1819   }
1820   for (i = 0; i < m; i++) {
1821     for (j = 0; j < 3 - sdim; j++) dxm++;
1822     tmp = *dxm++ - starts[0];
1823     for (j = 0; j < dim - 1; j++) {
1824       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1825       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1826     }
1827     if (mat->stencil.noc) dxm++;
1828     jdxm[i] = tmp;
1829   }
1830   for (i = 0; i < n; i++) {
1831     for (j = 0; j < 3 - sdim; j++) dxn++;
1832     tmp = *dxn++ - starts[0];
1833     for (j = 0; j < dim - 1; j++) {
1834       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1835       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1836     }
1837     if (mat->stencil.noc) dxn++;
1838     jdxn[i] = tmp;
1839   }
1840   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1841   PetscCall(PetscFree2(bufm, bufn));
1842   PetscFunctionReturn(PETSC_SUCCESS);
1843 }
1844 
1845 /*@
1846   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1847   Using structured grid indexing
1848 
1849   Not Collective
1850 
1851   Input Parameters:
1852 + mat  - the matrix
1853 . m    - number of rows being entered
1854 . idxm - grid coordinates for matrix rows being entered
1855 . n    - number of columns being entered
1856 . idxn - grid coordinates for matrix columns being entered
1857 . v    - a logically two-dimensional array of values
1858 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1859 
1860   Level: beginner
1861 
1862   Notes:
1863   By default the values, `v`, are row-oriented and unsorted.
1864   See `MatSetOption()` for other options.
1865 
1866   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1867   options cannot be mixed without intervening calls to the assembly
1868   routines.
1869 
1870   The grid coordinates are across the entire grid, not just the local portion
1871 
1872   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1873   as well as in C.
1874 
1875   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1876 
1877   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1878   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1879 
1880   The columns and rows in the stencil passed in MUST be contained within the
1881   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1882   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1883   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1884   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1885 
1886   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1887   simply ignored. This allows easily inserting element stiffness matrices
1888   with homogeneous Dirichlet boundary conditions that you don't want represented
1889   in the matrix.
1890 
1891   Inspired by the structured grid interface to the HYPRE package
1892   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1893 
1894   Fortran Note:
1895   `idxm` and `idxn` should be declared as
1896 .vb
1897     MatStencil idxm(4,m),idxn(4,n)
1898 .ve
1899   and the values inserted using
1900 .vb
1901     idxm(MatStencil_i,1) = i
1902     idxm(MatStencil_j,1) = j
1903     idxm(MatStencil_k,1) = k
1904    etc
1905 .ve
1906 
1907 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1908           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1909           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1910 @*/
1911 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1912 {
1913   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1914   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1915   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1916 
1917   PetscFunctionBegin;
1918   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1920   PetscValidType(mat, 1);
1921   PetscAssertPointer(idxm, 3);
1922   PetscAssertPointer(idxn, 5);
1923   PetscAssertPointer(v, 6);
1924 
1925   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1926     jdxm = buf;
1927     jdxn = buf + m;
1928   } else {
1929     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1930     jdxm = bufm;
1931     jdxn = bufn;
1932   }
1933   for (i = 0; i < m; i++) {
1934     for (j = 0; j < 3 - sdim; j++) dxm++;
1935     tmp = *dxm++ - starts[0];
1936     for (j = 0; j < sdim - 1; j++) {
1937       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1938       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1939     }
1940     dxm++;
1941     jdxm[i] = tmp;
1942   }
1943   for (i = 0; i < n; i++) {
1944     for (j = 0; j < 3 - sdim; j++) dxn++;
1945     tmp = *dxn++ - starts[0];
1946     for (j = 0; j < sdim - 1; j++) {
1947       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1948       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1949     }
1950     dxn++;
1951     jdxn[i] = tmp;
1952   }
1953   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1954   PetscCall(PetscFree2(bufm, bufn));
1955   PetscFunctionReturn(PETSC_SUCCESS);
1956 }
1957 
1958 /*@
1959   MatSetStencil - Sets the grid information for setting values into a matrix via
1960   `MatSetValuesStencil()`
1961 
1962   Not Collective
1963 
1964   Input Parameters:
1965 + mat    - the matrix
1966 . dim    - dimension of the grid 1, 2, or 3
1967 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1968 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1969 - dof    - number of degrees of freedom per node
1970 
1971   Level: beginner
1972 
1973   Notes:
1974   Inspired by the structured grid interface to the HYPRE package
1975   (www.llnl.gov/CASC/hyper)
1976 
1977   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1978   user.
1979 
1980 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1981           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1982 @*/
1983 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1984 {
1985   PetscFunctionBegin;
1986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1987   PetscAssertPointer(dims, 3);
1988   PetscAssertPointer(starts, 4);
1989 
1990   mat->stencil.dim = dim + (dof > 1);
1991   for (PetscInt i = 0; i < dim; i++) {
1992     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1993     mat->stencil.starts[i] = starts[dim - i - 1];
1994   }
1995   mat->stencil.dims[dim]   = dof;
1996   mat->stencil.starts[dim] = 0;
1997   mat->stencil.noc         = (PetscBool)(dof == 1);
1998   PetscFunctionReturn(PETSC_SUCCESS);
1999 }
2000 
2001 /*@
2002   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2003 
2004   Not Collective
2005 
2006   Input Parameters:
2007 + mat  - the matrix
2008 . m    - the number of block rows
2009 . idxm - the global block indices
2010 . n    - the number of block columns
2011 . idxn - the global block indices
2012 . v    - a logically two-dimensional array of values
2013 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2014 
2015   Level: intermediate
2016 
2017   Notes:
2018   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2019   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2020 
2021   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2022   NOT the total number of rows/columns; for example, if the block size is 2 and
2023   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
2024   The values in `idxm` would be 1 2; that is the first index for each block divided by
2025   the block size.
2026 
2027   You must call `MatSetBlockSize()` when constructing this matrix (before
2028   preallocating it).
2029 
2030   By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order.
2031 
2032   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2033   options cannot be mixed without intervening calls to the assembly
2034   routines.
2035 
2036   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2037   as well as in C.
2038 
2039   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2040   simply ignored. This allows easily inserting element stiffness matrices
2041   with homogeneous Dirichlet boundary conditions that you don't want represented
2042   in the matrix.
2043 
2044   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2045   internal searching must be done to determine where to place the
2046   data in the matrix storage space.  By instead inserting blocks of
2047   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2048   reduced.
2049 
2050   Example:
2051 .vb
2052    Suppose m=n=2 and block size(bs) = 2 The array is
2053 
2054    1  2  | 3  4
2055    5  6  | 7  8
2056    - - - | - - -
2057    9  10 | 11 12
2058    13 14 | 15 16
2059 
2060    v[] should be passed in like
2061    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2062 
2063   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2064    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2065 .ve
2066 
2067   Fortran Notes:
2068   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2069 .vb
2070   call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
2071 .ve
2072 
2073   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2074 
2075 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2076 @*/
2077 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2078 {
2079   PetscFunctionBeginHot;
2080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2081   PetscValidType(mat, 1);
2082   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2083   PetscAssertPointer(idxm, 3);
2084   PetscAssertPointer(idxn, 5);
2085   MatCheckPreallocated(mat, 1);
2086   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2087   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2088   if (PetscDefined(USE_DEBUG)) {
2089     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2090     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2091   }
2092   if (PetscDefined(USE_DEBUG)) {
2093     PetscInt rbs, cbs, M, N, i;
2094     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2095     PetscCall(MatGetSize(mat, &M, &N));
2096     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M);
2097     for (i = 0; i < n; i++)
2098       PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N);
2099   }
2100   if (mat->assembled) {
2101     mat->was_assembled = PETSC_TRUE;
2102     mat->assembled     = PETSC_FALSE;
2103   }
2104   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2105   if (mat->ops->setvaluesblocked) {
2106     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2107   } else {
2108     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2109     PetscInt i, j, bs, cbs;
2110 
2111     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2112     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2113       iidxm = buf;
2114       iidxn = buf + m * bs;
2115     } else {
2116       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2117       iidxm = bufr;
2118       iidxn = bufc;
2119     }
2120     for (i = 0; i < m; i++) {
2121       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2122     }
2123     if (m != n || bs != cbs || idxm != idxn) {
2124       for (i = 0; i < n; i++) {
2125         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2126       }
2127     } else iidxn = iidxm;
2128     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2129     PetscCall(PetscFree2(bufr, bufc));
2130   }
2131   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2132   PetscFunctionReturn(PETSC_SUCCESS);
2133 }
2134 
2135 /*@
2136   MatGetValues - Gets a block of local values from a matrix.
2137 
2138   Not Collective; can only return values that are owned by the give process
2139 
2140   Input Parameters:
2141 + mat  - the matrix
2142 . v    - a logically two-dimensional array for storing the values
2143 . m    - the number of rows
2144 . idxm - the  global indices of the rows
2145 . n    - the number of columns
2146 - idxn - the global indices of the columns
2147 
2148   Level: advanced
2149 
2150   Notes:
2151   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2152   The values, `v`, are then returned in a row-oriented format,
2153   analogous to that used by default in `MatSetValues()`.
2154 
2155   `MatGetValues()` uses 0-based row and column numbers in
2156   Fortran as well as in C.
2157 
2158   `MatGetValues()` requires that the matrix has been assembled
2159   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2160   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2161   without intermediate matrix assembly.
2162 
2163   Negative row or column indices will be ignored and those locations in `v` will be
2164   left unchanged.
2165 
2166   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2167   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2168   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2169 
2170 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2171 @*/
2172 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2173 {
2174   PetscFunctionBegin;
2175   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2176   PetscValidType(mat, 1);
2177   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2178   PetscAssertPointer(idxm, 3);
2179   PetscAssertPointer(idxn, 5);
2180   PetscAssertPointer(v, 6);
2181   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2182   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2183   MatCheckPreallocated(mat, 1);
2184 
2185   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2186   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2187   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2188   PetscFunctionReturn(PETSC_SUCCESS);
2189 }
2190 
2191 /*@
2192   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2193   defined previously by `MatSetLocalToGlobalMapping()`
2194 
2195   Not Collective
2196 
2197   Input Parameters:
2198 + mat  - the matrix
2199 . nrow - number of rows
2200 . irow - the row local indices
2201 . ncol - number of columns
2202 - icol - the column local indices
2203 
2204   Output Parameter:
2205 . y - a logically two-dimensional array of values
2206 
2207   Level: advanced
2208 
2209   Notes:
2210   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2211 
2212   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,
2213   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2214   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2215   with `MatSetLocalToGlobalMapping()`.
2216 
2217 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2218           `MatSetValuesLocal()`, `MatGetValues()`
2219 @*/
2220 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2221 {
2222   PetscFunctionBeginHot;
2223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2224   PetscValidType(mat, 1);
2225   MatCheckPreallocated(mat, 1);
2226   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2227   PetscAssertPointer(irow, 3);
2228   PetscAssertPointer(icol, 5);
2229   if (PetscDefined(USE_DEBUG)) {
2230     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2231     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2232   }
2233   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2234   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2235   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2236   else {
2237     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2238     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2239       irowm = buf;
2240       icolm = buf + nrow;
2241     } else {
2242       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2243       irowm = bufr;
2244       icolm = bufc;
2245     }
2246     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2247     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2248     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2249     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2250     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2251     PetscCall(PetscFree2(bufr, bufc));
2252   }
2253   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2254   PetscFunctionReturn(PETSC_SUCCESS);
2255 }
2256 
2257 /*@
2258   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2259   the same size. Currently, this can only be called once and creates the given matrix.
2260 
2261   Not Collective
2262 
2263   Input Parameters:
2264 + mat  - the matrix
2265 . nb   - the number of blocks
2266 . bs   - the number of rows (and columns) in each block
2267 . rows - a concatenation of the rows for each block
2268 - v    - a concatenation of logically two-dimensional arrays of values
2269 
2270   Level: advanced
2271 
2272   Notes:
2273   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2274 
2275   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2276 
2277 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2278           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2279 @*/
2280 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2281 {
2282   PetscFunctionBegin;
2283   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2284   PetscValidType(mat, 1);
2285   PetscAssertPointer(rows, 4);
2286   PetscAssertPointer(v, 5);
2287   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2288 
2289   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2290   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2291   else {
2292     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2293   }
2294   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2295   PetscFunctionReturn(PETSC_SUCCESS);
2296 }
2297 
2298 /*@
2299   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2300   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2301   using a local (per-processor) numbering.
2302 
2303   Not Collective
2304 
2305   Input Parameters:
2306 + x        - the matrix
2307 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2308 - cmapping - column mapping
2309 
2310   Level: intermediate
2311 
2312   Note:
2313   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2314 
2315 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2316 @*/
2317 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2318 {
2319   PetscFunctionBegin;
2320   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2321   PetscValidType(x, 1);
2322   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2323   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2324   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2325   else {
2326     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2327     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2328   }
2329   PetscFunctionReturn(PETSC_SUCCESS);
2330 }
2331 
2332 /*@
2333   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2334 
2335   Not Collective
2336 
2337   Input Parameter:
2338 . A - the matrix
2339 
2340   Output Parameters:
2341 + rmapping - row mapping
2342 - cmapping - column mapping
2343 
2344   Level: advanced
2345 
2346 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2347 @*/
2348 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2349 {
2350   PetscFunctionBegin;
2351   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2352   PetscValidType(A, 1);
2353   if (rmapping) {
2354     PetscAssertPointer(rmapping, 2);
2355     *rmapping = A->rmap->mapping;
2356   }
2357   if (cmapping) {
2358     PetscAssertPointer(cmapping, 3);
2359     *cmapping = A->cmap->mapping;
2360   }
2361   PetscFunctionReturn(PETSC_SUCCESS);
2362 }
2363 
2364 /*@
2365   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2366 
2367   Logically Collective
2368 
2369   Input Parameters:
2370 + A    - the matrix
2371 . rmap - row layout
2372 - cmap - column layout
2373 
2374   Level: advanced
2375 
2376   Note:
2377   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2378 
2379 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2380 @*/
2381 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2382 {
2383   PetscFunctionBegin;
2384   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2385   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2386   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2387   PetscFunctionReturn(PETSC_SUCCESS);
2388 }
2389 
2390 /*@
2391   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2392 
2393   Not Collective
2394 
2395   Input Parameter:
2396 . A - the matrix
2397 
2398   Output Parameters:
2399 + rmap - row layout
2400 - cmap - column layout
2401 
2402   Level: advanced
2403 
2404 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2405 @*/
2406 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2407 {
2408   PetscFunctionBegin;
2409   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2410   PetscValidType(A, 1);
2411   if (rmap) {
2412     PetscAssertPointer(rmap, 2);
2413     *rmap = A->rmap;
2414   }
2415   if (cmap) {
2416     PetscAssertPointer(cmap, 3);
2417     *cmap = A->cmap;
2418   }
2419   PetscFunctionReturn(PETSC_SUCCESS);
2420 }
2421 
2422 /*@
2423   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2424   using a local numbering of the rows and columns.
2425 
2426   Not Collective
2427 
2428   Input Parameters:
2429 + mat  - the matrix
2430 . nrow - number of rows
2431 . irow - the row local indices
2432 . ncol - number of columns
2433 . icol - the column local indices
2434 . y    - a logically two-dimensional array of values
2435 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2436 
2437   Level: intermediate
2438 
2439   Notes:
2440   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2441 
2442   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2443   options cannot be mixed without intervening calls to the assembly
2444   routines.
2445 
2446   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2447   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2448 
2449   Fortran Notes:
2450   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2451 .vb
2452   call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2453 .ve
2454 
2455   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2456 
2457 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2458           `MatGetValuesLocal()`
2459 @*/
2460 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2461 {
2462   PetscFunctionBeginHot;
2463   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2464   PetscValidType(mat, 1);
2465   MatCheckPreallocated(mat, 1);
2466   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2467   PetscAssertPointer(irow, 3);
2468   PetscAssertPointer(icol, 5);
2469   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2470   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2471   if (PetscDefined(USE_DEBUG)) {
2472     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2473     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2474   }
2475 
2476   if (mat->assembled) {
2477     mat->was_assembled = PETSC_TRUE;
2478     mat->assembled     = PETSC_FALSE;
2479   }
2480   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2481   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2482   else {
2483     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2484     const PetscInt *irowm, *icolm;
2485 
2486     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2487       bufr  = buf;
2488       bufc  = buf + nrow;
2489       irowm = bufr;
2490       icolm = bufc;
2491     } else {
2492       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2493       irowm = bufr;
2494       icolm = bufc;
2495     }
2496     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2497     else irowm = irow;
2498     if (mat->cmap->mapping) {
2499       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2500         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2501       } else icolm = irowm;
2502     } else icolm = icol;
2503     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2504     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2505   }
2506   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2507   PetscFunctionReturn(PETSC_SUCCESS);
2508 }
2509 
2510 /*@
2511   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2512   using a local ordering of the nodes a block at a time.
2513 
2514   Not Collective
2515 
2516   Input Parameters:
2517 + mat  - the matrix
2518 . nrow - number of rows
2519 . irow - the row local indices
2520 . ncol - number of columns
2521 . icol - the column local indices
2522 . y    - a logically two-dimensional array of values
2523 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2524 
2525   Level: intermediate
2526 
2527   Notes:
2528   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2529   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2530 
2531   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2532   options cannot be mixed without intervening calls to the assembly
2533   routines.
2534 
2535   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2536   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2537 
2538   Fortran Notes:
2539   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2540 .vb
2541   call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2542 .ve
2543 
2544   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2545 
2546 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2547           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2548 @*/
2549 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2550 {
2551   PetscFunctionBeginHot;
2552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2553   PetscValidType(mat, 1);
2554   MatCheckPreallocated(mat, 1);
2555   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2556   PetscAssertPointer(irow, 3);
2557   PetscAssertPointer(icol, 5);
2558   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2559   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2560   if (PetscDefined(USE_DEBUG)) {
2561     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2562     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);
2563   }
2564 
2565   if (mat->assembled) {
2566     mat->was_assembled = PETSC_TRUE;
2567     mat->assembled     = PETSC_FALSE;
2568   }
2569   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2570     PetscInt irbs, rbs;
2571     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2572     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2573     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2574   }
2575   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2576     PetscInt icbs, cbs;
2577     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2578     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2579     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2580   }
2581   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2582   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2583   else {
2584     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2585     const PetscInt *irowm, *icolm;
2586 
2587     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2588       bufr  = buf;
2589       bufc  = buf + nrow;
2590       irowm = bufr;
2591       icolm = bufc;
2592     } else {
2593       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2594       irowm = bufr;
2595       icolm = bufc;
2596     }
2597     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2598     else irowm = irow;
2599     if (mat->cmap->mapping) {
2600       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2601         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2602       } else icolm = irowm;
2603     } else icolm = icol;
2604     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2605     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2606   }
2607   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2608   PetscFunctionReturn(PETSC_SUCCESS);
2609 }
2610 
2611 /*@
2612   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2613 
2614   Collective
2615 
2616   Input Parameters:
2617 + mat - the matrix
2618 - x   - the vector to be multiplied
2619 
2620   Output Parameter:
2621 . y - the result
2622 
2623   Level: developer
2624 
2625   Note:
2626   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2627   call `MatMultDiagonalBlock`(A,y,y).
2628 
2629 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2630 @*/
2631 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2632 {
2633   PetscFunctionBegin;
2634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2635   PetscValidType(mat, 1);
2636   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2637   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2638 
2639   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2640   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2641   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2642   MatCheckPreallocated(mat, 1);
2643 
2644   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2645   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2646   PetscFunctionReturn(PETSC_SUCCESS);
2647 }
2648 
2649 /*@
2650   MatMult - Computes the matrix-vector product, $y = Ax$.
2651 
2652   Neighbor-wise Collective
2653 
2654   Input Parameters:
2655 + mat - the matrix
2656 - x   - the vector to be multiplied
2657 
2658   Output Parameter:
2659 . y - the result
2660 
2661   Level: beginner
2662 
2663   Note:
2664   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2665   call `MatMult`(A,y,y).
2666 
2667 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2668 @*/
2669 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2670 {
2671   PetscFunctionBegin;
2672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2673   PetscValidType(mat, 1);
2674   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2675   VecCheckAssembled(x);
2676   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2677   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2678   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2679   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2680   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);
2681   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);
2682   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);
2683   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);
2684   PetscCall(VecSetErrorIfLocked(y, 3));
2685   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2686   MatCheckPreallocated(mat, 1);
2687 
2688   PetscCall(VecLockReadPush(x));
2689   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2690   PetscUseTypeMethod(mat, mult, x, y);
2691   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2692   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2693   PetscCall(VecLockReadPop(x));
2694   PetscFunctionReturn(PETSC_SUCCESS);
2695 }
2696 
2697 /*@
2698   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2699 
2700   Neighbor-wise Collective
2701 
2702   Input Parameters:
2703 + mat - the matrix
2704 - x   - the vector to be multiplied
2705 
2706   Output Parameter:
2707 . y - the result
2708 
2709   Level: beginner
2710 
2711   Notes:
2712   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2713   call `MatMultTranspose`(A,y,y).
2714 
2715   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2716   use `MatMultHermitianTranspose()`
2717 
2718 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2719 @*/
2720 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2721 {
2722   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2723 
2724   PetscFunctionBegin;
2725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2726   PetscValidType(mat, 1);
2727   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2728   VecCheckAssembled(x);
2729   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2730 
2731   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2732   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2733   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2734   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);
2735   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);
2736   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);
2737   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);
2738   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2739   MatCheckPreallocated(mat, 1);
2740 
2741   if (!mat->ops->multtranspose) {
2742     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2743     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);
2744   } else op = mat->ops->multtranspose;
2745   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2746   PetscCall(VecLockReadPush(x));
2747   PetscCall((*op)(mat, x, y));
2748   PetscCall(VecLockReadPop(x));
2749   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2750   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2751   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2752   PetscFunctionReturn(PETSC_SUCCESS);
2753 }
2754 
2755 /*@
2756   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2757 
2758   Neighbor-wise Collective
2759 
2760   Input Parameters:
2761 + mat - the matrix
2762 - x   - the vector to be multiplied
2763 
2764   Output Parameter:
2765 . y - the result
2766 
2767   Level: beginner
2768 
2769   Notes:
2770   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2771   call `MatMultHermitianTranspose`(A,y,y).
2772 
2773   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2774 
2775   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2776 
2777 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2778 @*/
2779 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2780 {
2781   PetscFunctionBegin;
2782   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2783   PetscValidType(mat, 1);
2784   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2785   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2786 
2787   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2788   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2789   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2790   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);
2791   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);
2792   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);
2793   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);
2794   MatCheckPreallocated(mat, 1);
2795 
2796   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2797 #if defined(PETSC_USE_COMPLEX)
2798   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2799     PetscCall(VecLockReadPush(x));
2800     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2801     else PetscUseTypeMethod(mat, mult, x, y);
2802     PetscCall(VecLockReadPop(x));
2803   } else {
2804     Vec w;
2805     PetscCall(VecDuplicate(x, &w));
2806     PetscCall(VecCopy(x, w));
2807     PetscCall(VecConjugate(w));
2808     PetscCall(MatMultTranspose(mat, w, y));
2809     PetscCall(VecDestroy(&w));
2810     PetscCall(VecConjugate(y));
2811   }
2812   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2813 #else
2814   PetscCall(MatMultTranspose(mat, x, y));
2815 #endif
2816   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2817   PetscFunctionReturn(PETSC_SUCCESS);
2818 }
2819 
2820 /*@
2821   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2822 
2823   Neighbor-wise Collective
2824 
2825   Input Parameters:
2826 + mat - the matrix
2827 . v1  - the vector to be multiplied by `mat`
2828 - v2  - the vector to be added to the result
2829 
2830   Output Parameter:
2831 . v3 - the result
2832 
2833   Level: beginner
2834 
2835   Note:
2836   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2837   call `MatMultAdd`(A,v1,v2,v1).
2838 
2839 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2840 @*/
2841 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2842 {
2843   PetscFunctionBegin;
2844   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2845   PetscValidType(mat, 1);
2846   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2847   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2848   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2849 
2850   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2851   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2852   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);
2853   /* 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);
2854      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); */
2855   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);
2856   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);
2857   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2858   MatCheckPreallocated(mat, 1);
2859 
2860   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2861   PetscCall(VecLockReadPush(v1));
2862   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2863   PetscCall(VecLockReadPop(v1));
2864   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2865   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2866   PetscFunctionReturn(PETSC_SUCCESS);
2867 }
2868 
2869 /*@
2870   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2871 
2872   Neighbor-wise Collective
2873 
2874   Input Parameters:
2875 + mat - the matrix
2876 . v1  - the vector to be multiplied by the transpose of the matrix
2877 - v2  - the vector to be added to the result
2878 
2879   Output Parameter:
2880 . v3 - the result
2881 
2882   Level: beginner
2883 
2884   Note:
2885   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2886   call `MatMultTransposeAdd`(A,v1,v2,v1).
2887 
2888 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2889 @*/
2890 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2891 {
2892   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2893 
2894   PetscFunctionBegin;
2895   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2896   PetscValidType(mat, 1);
2897   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2898   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2899   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2900 
2901   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2902   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2903   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);
2904   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);
2905   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);
2906   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2907   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2908   MatCheckPreallocated(mat, 1);
2909 
2910   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2911   PetscCall(VecLockReadPush(v1));
2912   PetscCall((*op)(mat, v1, v2, v3));
2913   PetscCall(VecLockReadPop(v1));
2914   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2915   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2916   PetscFunctionReturn(PETSC_SUCCESS);
2917 }
2918 
2919 /*@
2920   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2921 
2922   Neighbor-wise Collective
2923 
2924   Input Parameters:
2925 + mat - the matrix
2926 . v1  - the vector to be multiplied by the Hermitian transpose
2927 - v2  - the vector to be added to the result
2928 
2929   Output Parameter:
2930 . v3 - the result
2931 
2932   Level: beginner
2933 
2934   Note:
2935   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2936   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2937 
2938 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2939 @*/
2940 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2941 {
2942   PetscFunctionBegin;
2943   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2944   PetscValidType(mat, 1);
2945   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2946   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2947   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2948 
2949   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2950   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2951   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2952   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);
2953   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);
2954   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);
2955   MatCheckPreallocated(mat, 1);
2956 
2957   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2958   PetscCall(VecLockReadPush(v1));
2959   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2960   else {
2961     Vec w, z;
2962     PetscCall(VecDuplicate(v1, &w));
2963     PetscCall(VecCopy(v1, w));
2964     PetscCall(VecConjugate(w));
2965     PetscCall(VecDuplicate(v3, &z));
2966     PetscCall(MatMultTranspose(mat, w, z));
2967     PetscCall(VecDestroy(&w));
2968     PetscCall(VecConjugate(z));
2969     if (v2 != v3) {
2970       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2971     } else {
2972       PetscCall(VecAXPY(v3, 1.0, z));
2973     }
2974     PetscCall(VecDestroy(&z));
2975   }
2976   PetscCall(VecLockReadPop(v1));
2977   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2978   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2979   PetscFunctionReturn(PETSC_SUCCESS);
2980 }
2981 
2982 /*@
2983   MatGetFactorType - gets the type of factorization a matrix is
2984 
2985   Not Collective
2986 
2987   Input Parameter:
2988 . mat - the matrix
2989 
2990   Output Parameter:
2991 . 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`
2992 
2993   Level: intermediate
2994 
2995 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2996           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2997 @*/
2998 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2999 {
3000   PetscFunctionBegin;
3001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3002   PetscValidType(mat, 1);
3003   PetscAssertPointer(t, 2);
3004   *t = mat->factortype;
3005   PetscFunctionReturn(PETSC_SUCCESS);
3006 }
3007 
3008 /*@
3009   MatSetFactorType - sets the type of factorization a matrix is
3010 
3011   Logically Collective
3012 
3013   Input Parameters:
3014 + mat - the matrix
3015 - 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`
3016 
3017   Level: intermediate
3018 
3019 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3020           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3021 @*/
3022 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3023 {
3024   PetscFunctionBegin;
3025   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3026   PetscValidType(mat, 1);
3027   mat->factortype = t;
3028   PetscFunctionReturn(PETSC_SUCCESS);
3029 }
3030 
3031 /*@
3032   MatGetInfo - Returns information about matrix storage (number of
3033   nonzeros, memory, etc.).
3034 
3035   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3036 
3037   Input Parameters:
3038 + mat  - the matrix
3039 - 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)
3040 
3041   Output Parameter:
3042 . info - matrix information context
3043 
3044   Options Database Key:
3045 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3046 
3047   Level: intermediate
3048 
3049   Notes:
3050   The `MatInfo` context contains a variety of matrix data, including
3051   number of nonzeros allocated and used, number of mallocs during
3052   matrix assembly, etc.  Additional information for factored matrices
3053   is provided (such as the fill ratio, number of mallocs during
3054   factorization, etc.).
3055 
3056   Example:
3057   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3058   data within the `MatInfo` context.  For example,
3059 .vb
3060       MatInfo info;
3061       Mat     A;
3062       double  mal, nz_a, nz_u;
3063 
3064       MatGetInfo(A, MAT_LOCAL, &info);
3065       mal  = info.mallocs;
3066       nz_a = info.nz_allocated;
3067 .ve
3068 
3069 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3070 @*/
3071 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3072 {
3073   PetscFunctionBegin;
3074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3075   PetscValidType(mat, 1);
3076   PetscAssertPointer(info, 3);
3077   MatCheckPreallocated(mat, 1);
3078   PetscUseTypeMethod(mat, getinfo, flag, info);
3079   PetscFunctionReturn(PETSC_SUCCESS);
3080 }
3081 
3082 /*
3083    This is used by external packages where it is not easy to get the info from the actual
3084    matrix factorization.
3085 */
3086 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3087 {
3088   PetscFunctionBegin;
3089   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3090   PetscFunctionReturn(PETSC_SUCCESS);
3091 }
3092 
3093 /*@
3094   MatLUFactor - Performs in-place LU factorization of matrix.
3095 
3096   Collective
3097 
3098   Input Parameters:
3099 + mat  - the matrix
3100 . row  - row permutation
3101 . col  - column permutation
3102 - info - options for factorization, includes
3103 .vb
3104           fill - expected fill as ratio of original fill.
3105           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3106                    Run with the option -info to determine an optimal value to use
3107 .ve
3108 
3109   Level: developer
3110 
3111   Notes:
3112   Most users should employ the `KSP` interface for linear solvers
3113   instead of working directly with matrix algebra routines such as this.
3114   See, e.g., `KSPCreate()`.
3115 
3116   This changes the state of the matrix to a factored matrix; it cannot be used
3117   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3118 
3119   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3120   when not using `KSP`.
3121 
3122   Fortran Note:
3123   A valid (non-null) `info` argument must be provided
3124 
3125 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3126           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3127 @*/
3128 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3129 {
3130   MatFactorInfo tinfo;
3131 
3132   PetscFunctionBegin;
3133   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3134   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3135   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3136   if (info) PetscAssertPointer(info, 4);
3137   PetscValidType(mat, 1);
3138   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3139   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3140   MatCheckPreallocated(mat, 1);
3141   if (!info) {
3142     PetscCall(MatFactorInfoInitialize(&tinfo));
3143     info = &tinfo;
3144   }
3145 
3146   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3147   PetscUseTypeMethod(mat, lufactor, row, col, info);
3148   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3149   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3150   PetscFunctionReturn(PETSC_SUCCESS);
3151 }
3152 
3153 /*@
3154   MatILUFactor - Performs in-place ILU factorization of matrix.
3155 
3156   Collective
3157 
3158   Input Parameters:
3159 + mat  - the matrix
3160 . row  - row permutation
3161 . col  - column permutation
3162 - info - structure containing
3163 .vb
3164       levels - number of levels of fill.
3165       expected fill - as ratio of original fill.
3166       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3167                 missing diagonal entries)
3168 .ve
3169 
3170   Level: developer
3171 
3172   Notes:
3173   Most users should employ the `KSP` interface for linear solvers
3174   instead of working directly with matrix algebra routines such as this.
3175   See, e.g., `KSPCreate()`.
3176 
3177   Probably really in-place only when level of fill is zero, otherwise allocates
3178   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3179   when not using `KSP`.
3180 
3181   Fortran Note:
3182   A valid (non-null) `info` argument must be provided
3183 
3184 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3185 @*/
3186 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3187 {
3188   PetscFunctionBegin;
3189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3190   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3191   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3192   PetscAssertPointer(info, 4);
3193   PetscValidType(mat, 1);
3194   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3195   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3196   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3197   MatCheckPreallocated(mat, 1);
3198 
3199   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3200   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3201   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3202   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3203   PetscFunctionReturn(PETSC_SUCCESS);
3204 }
3205 
3206 /*@
3207   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3208   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3209 
3210   Collective
3211 
3212   Input Parameters:
3213 + fact - the factor matrix obtained with `MatGetFactor()`
3214 . mat  - the matrix
3215 . row  - the row permutation
3216 . col  - the column permutation
3217 - info - options for factorization, includes
3218 .vb
3219           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3220           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3221 .ve
3222 
3223   Level: developer
3224 
3225   Notes:
3226   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3227 
3228   Most users should employ the simplified `KSP` interface for linear solvers
3229   instead of working directly with matrix algebra routines such as this.
3230   See, e.g., `KSPCreate()`.
3231 
3232   Fortran Note:
3233   A valid (non-null) `info` argument must be provided
3234 
3235 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3236 @*/
3237 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3238 {
3239   MatFactorInfo tinfo;
3240 
3241   PetscFunctionBegin;
3242   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3244   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3245   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3246   if (info) PetscAssertPointer(info, 5);
3247   PetscValidType(fact, 1);
3248   PetscValidType(mat, 2);
3249   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3250   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3251   MatCheckPreallocated(mat, 2);
3252   if (!info) {
3253     PetscCall(MatFactorInfoInitialize(&tinfo));
3254     info = &tinfo;
3255   }
3256 
3257   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3258   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3259   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3260   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3261   PetscFunctionReturn(PETSC_SUCCESS);
3262 }
3263 
3264 /*@
3265   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3266   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3267 
3268   Collective
3269 
3270   Input Parameters:
3271 + fact - the factor matrix obtained with `MatGetFactor()`
3272 . mat  - the matrix
3273 - info - options for factorization
3274 
3275   Level: developer
3276 
3277   Notes:
3278   See `MatLUFactor()` for in-place factorization.  See
3279   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3280 
3281   Most users should employ the `KSP` interface for linear solvers
3282   instead of working directly with matrix algebra routines such as this.
3283   See, e.g., `KSPCreate()`.
3284 
3285   Fortran Note:
3286   A valid (non-null) `info` argument must be provided
3287 
3288 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3289 @*/
3290 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3291 {
3292   MatFactorInfo tinfo;
3293 
3294   PetscFunctionBegin;
3295   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3296   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3297   PetscValidType(fact, 1);
3298   PetscValidType(mat, 2);
3299   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3300   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,
3301              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3302 
3303   MatCheckPreallocated(mat, 2);
3304   if (!info) {
3305     PetscCall(MatFactorInfoInitialize(&tinfo));
3306     info = &tinfo;
3307   }
3308 
3309   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3310   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3311   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3312   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3313   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3314   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3315   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3316   PetscFunctionReturn(PETSC_SUCCESS);
3317 }
3318 
3319 /*@
3320   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3321   symmetric matrix.
3322 
3323   Collective
3324 
3325   Input Parameters:
3326 + mat  - the matrix
3327 . perm - row and column permutations
3328 - info - expected fill as ratio of original fill
3329 
3330   Level: developer
3331 
3332   Notes:
3333   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3334   `MatCholeskyFactorSymbolic()`, 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   Fortran Note:
3341   A valid (non-null) `info` argument must be provided
3342 
3343 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3344           `MatGetOrdering()`
3345 @*/
3346 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3347 {
3348   MatFactorInfo tinfo;
3349 
3350   PetscFunctionBegin;
3351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3352   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3353   if (info) PetscAssertPointer(info, 3);
3354   PetscValidType(mat, 1);
3355   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3356   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3357   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3358   MatCheckPreallocated(mat, 1);
3359   if (!info) {
3360     PetscCall(MatFactorInfoInitialize(&tinfo));
3361     info = &tinfo;
3362   }
3363 
3364   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3365   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3366   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3367   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3368   PetscFunctionReturn(PETSC_SUCCESS);
3369 }
3370 
3371 /*@
3372   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3373   of a symmetric matrix.
3374 
3375   Collective
3376 
3377   Input Parameters:
3378 + fact - the factor matrix obtained with `MatGetFactor()`
3379 . mat  - the matrix
3380 . perm - row and column permutations
3381 - info - options for factorization, includes
3382 .vb
3383           fill - expected fill as ratio of original fill.
3384           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3385                    Run with the option -info to determine an optimal value to use
3386 .ve
3387 
3388   Level: developer
3389 
3390   Notes:
3391   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3392   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3393 
3394   Most users should employ the `KSP` interface for linear solvers
3395   instead of working directly with matrix algebra routines such as this.
3396   See, e.g., `KSPCreate()`.
3397 
3398   Fortran Note:
3399   A valid (non-null) `info` argument must be provided
3400 
3401 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3402           `MatGetOrdering()`
3403 @*/
3404 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3405 {
3406   MatFactorInfo tinfo;
3407 
3408   PetscFunctionBegin;
3409   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3410   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3411   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3412   if (info) PetscAssertPointer(info, 4);
3413   PetscValidType(fact, 1);
3414   PetscValidType(mat, 2);
3415   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3416   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3417   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3418   MatCheckPreallocated(mat, 2);
3419   if (!info) {
3420     PetscCall(MatFactorInfoInitialize(&tinfo));
3421     info = &tinfo;
3422   }
3423 
3424   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3425   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3426   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3427   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3428   PetscFunctionReturn(PETSC_SUCCESS);
3429 }
3430 
3431 /*@
3432   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3433   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3434   `MatCholeskyFactorSymbolic()`.
3435 
3436   Collective
3437 
3438   Input Parameters:
3439 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3440 . mat  - the initial matrix that is to be factored
3441 - info - options for factorization
3442 
3443   Level: developer
3444 
3445   Note:
3446   Most users should employ the `KSP` interface for linear solvers
3447   instead of working directly with matrix algebra routines such as this.
3448   See, e.g., `KSPCreate()`.
3449 
3450   Fortran Note:
3451   A valid (non-null) `info` argument must be provided
3452 
3453 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3454 @*/
3455 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3456 {
3457   MatFactorInfo tinfo;
3458 
3459   PetscFunctionBegin;
3460   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3461   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3462   PetscValidType(fact, 1);
3463   PetscValidType(mat, 2);
3464   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3465   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,
3466              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3467   MatCheckPreallocated(mat, 2);
3468   if (!info) {
3469     PetscCall(MatFactorInfoInitialize(&tinfo));
3470     info = &tinfo;
3471   }
3472 
3473   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3474   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3475   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3476   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3477   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3478   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3479   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3480   PetscFunctionReturn(PETSC_SUCCESS);
3481 }
3482 
3483 /*@
3484   MatQRFactor - Performs in-place QR factorization of matrix.
3485 
3486   Collective
3487 
3488   Input Parameters:
3489 + mat  - the matrix
3490 . col  - column permutation
3491 - info - options for factorization, includes
3492 .vb
3493           fill - expected fill as ratio of original fill.
3494           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3495                    Run with the option -info to determine an optimal value to use
3496 .ve
3497 
3498   Level: developer
3499 
3500   Notes:
3501   Most users should employ the `KSP` interface for linear solvers
3502   instead of working directly with matrix algebra routines such as this.
3503   See, e.g., `KSPCreate()`.
3504 
3505   This changes the state of the matrix to a factored matrix; it cannot be used
3506   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3507 
3508   Fortran Note:
3509   A valid (non-null) `info` argument must be provided
3510 
3511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3512           `MatSetUnfactored()`
3513 @*/
3514 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3515 {
3516   PetscFunctionBegin;
3517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3518   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3519   if (info) PetscAssertPointer(info, 3);
3520   PetscValidType(mat, 1);
3521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3523   MatCheckPreallocated(mat, 1);
3524   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3525   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3526   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3527   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3528   PetscFunctionReturn(PETSC_SUCCESS);
3529 }
3530 
3531 /*@
3532   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3533   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3534 
3535   Collective
3536 
3537   Input Parameters:
3538 + fact - the factor matrix obtained with `MatGetFactor()`
3539 . mat  - the matrix
3540 . col  - column permutation
3541 - info - options for factorization, includes
3542 .vb
3543           fill - expected fill as ratio of original fill.
3544           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3545                    Run with the option -info to determine an optimal value to use
3546 .ve
3547 
3548   Level: developer
3549 
3550   Note:
3551   Most users should employ the `KSP` interface for linear solvers
3552   instead of working directly with matrix algebra routines such as this.
3553   See, e.g., `KSPCreate()`.
3554 
3555   Fortran Note:
3556   A valid (non-null) `info` argument must be provided
3557 
3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3559 @*/
3560 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3561 {
3562   MatFactorInfo tinfo;
3563 
3564   PetscFunctionBegin;
3565   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3567   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3568   if (info) PetscAssertPointer(info, 4);
3569   PetscValidType(fact, 1);
3570   PetscValidType(mat, 2);
3571   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3572   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3573   MatCheckPreallocated(mat, 2);
3574   if (!info) {
3575     PetscCall(MatFactorInfoInitialize(&tinfo));
3576     info = &tinfo;
3577   }
3578 
3579   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3580   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3581   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3582   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3583   PetscFunctionReturn(PETSC_SUCCESS);
3584 }
3585 
3586 /*@
3587   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3588   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3589 
3590   Collective
3591 
3592   Input Parameters:
3593 + fact - the factor matrix obtained with `MatGetFactor()`
3594 . mat  - the matrix
3595 - info - options for factorization
3596 
3597   Level: developer
3598 
3599   Notes:
3600   See `MatQRFactor()` for in-place factorization.
3601 
3602   Most users should employ the `KSP` interface for linear solvers
3603   instead of working directly with matrix algebra routines such as this.
3604   See, e.g., `KSPCreate()`.
3605 
3606   Fortran Note:
3607   A valid (non-null) `info` argument must be provided
3608 
3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3610 @*/
3611 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3612 {
3613   MatFactorInfo tinfo;
3614 
3615   PetscFunctionBegin;
3616   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3617   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3618   PetscValidType(fact, 1);
3619   PetscValidType(mat, 2);
3620   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3621   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,
3622              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3623 
3624   MatCheckPreallocated(mat, 2);
3625   if (!info) {
3626     PetscCall(MatFactorInfoInitialize(&tinfo));
3627     info = &tinfo;
3628   }
3629 
3630   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3631   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3632   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3633   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3634   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3635   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3636   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3637   PetscFunctionReturn(PETSC_SUCCESS);
3638 }
3639 
3640 /*@
3641   MatSolve - Solves $A x = b$, given a factored matrix.
3642 
3643   Neighbor-wise Collective
3644 
3645   Input Parameters:
3646 + mat - the factored matrix
3647 - b   - the right-hand-side vector
3648 
3649   Output Parameter:
3650 . x - the result vector
3651 
3652   Level: developer
3653 
3654   Notes:
3655   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3656   call `MatSolve`(A,x,x).
3657 
3658   Most users should employ the `KSP` interface for linear solvers
3659   instead of working directly with matrix algebra routines such as this.
3660   See, e.g., `KSPCreate()`.
3661 
3662 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3663 @*/
3664 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3665 {
3666   PetscFunctionBegin;
3667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3668   PetscValidType(mat, 1);
3669   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3670   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3671   PetscCheckSameComm(mat, 1, b, 2);
3672   PetscCheckSameComm(mat, 1, x, 3);
3673   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3674   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);
3675   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);
3676   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);
3677   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3678   MatCheckPreallocated(mat, 1);
3679 
3680   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3681   PetscCall(VecFlag(x, mat->factorerrortype));
3682   if (mat->factorerrortype) {
3683     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3684   } else PetscUseTypeMethod(mat, solve, b, x);
3685   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3686   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3687   PetscFunctionReturn(PETSC_SUCCESS);
3688 }
3689 
3690 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3691 {
3692   Vec      b, x;
3693   PetscInt N, i;
3694   PetscErrorCode (*f)(Mat, Vec, Vec);
3695   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3696 
3697   PetscFunctionBegin;
3698   if (A->factorerrortype) {
3699     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3700     PetscCall(MatSetInf(X));
3701     PetscFunctionReturn(PETSC_SUCCESS);
3702   }
3703   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3704   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3705   PetscCall(MatBoundToCPU(A, &Abound));
3706   if (!Abound) {
3707     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3708     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3709   }
3710 #if PetscDefined(HAVE_CUDA)
3711   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3712   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3713 #elif PetscDefined(HAVE_HIP)
3714   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3715   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3716 #endif
3717   PetscCall(MatGetSize(B, NULL, &N));
3718   for (i = 0; i < N; i++) {
3719     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3720     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3721     PetscCall((*f)(A, b, x));
3722     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3723     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3724   }
3725   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3726   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3727   PetscFunctionReturn(PETSC_SUCCESS);
3728 }
3729 
3730 /*@
3731   MatMatSolve - Solves $A X = B$, given a factored matrix.
3732 
3733   Neighbor-wise Collective
3734 
3735   Input Parameters:
3736 + A - the factored matrix
3737 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3738 
3739   Output Parameter:
3740 . X - the result matrix (dense matrix)
3741 
3742   Level: developer
3743 
3744   Note:
3745   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3746   otherwise, `B` and `X` cannot be the same.
3747 
3748 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3749 @*/
3750 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3751 {
3752   PetscFunctionBegin;
3753   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3754   PetscValidType(A, 1);
3755   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3756   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3757   PetscCheckSameComm(A, 1, B, 2);
3758   PetscCheckSameComm(A, 1, X, 3);
3759   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);
3760   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);
3761   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");
3762   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3763   MatCheckPreallocated(A, 1);
3764 
3765   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3766   if (!A->ops->matsolve) {
3767     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3768     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3769   } else PetscUseTypeMethod(A, matsolve, B, X);
3770   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3771   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3772   PetscFunctionReturn(PETSC_SUCCESS);
3773 }
3774 
3775 /*@
3776   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3777 
3778   Neighbor-wise Collective
3779 
3780   Input Parameters:
3781 + A - the factored matrix
3782 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3783 
3784   Output Parameter:
3785 . X - the result matrix (dense matrix)
3786 
3787   Level: developer
3788 
3789   Note:
3790   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3791   call `MatMatSolveTranspose`(A,X,X).
3792 
3793 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3794 @*/
3795 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3796 {
3797   PetscFunctionBegin;
3798   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3799   PetscValidType(A, 1);
3800   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3801   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3802   PetscCheckSameComm(A, 1, B, 2);
3803   PetscCheckSameComm(A, 1, X, 3);
3804   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3805   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);
3806   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);
3807   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);
3808   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");
3809   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3810   MatCheckPreallocated(A, 1);
3811 
3812   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3813   if (!A->ops->matsolvetranspose) {
3814     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3815     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3816   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3817   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3818   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3819   PetscFunctionReturn(PETSC_SUCCESS);
3820 }
3821 
3822 /*@
3823   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3824 
3825   Neighbor-wise Collective
3826 
3827   Input Parameters:
3828 + A  - the factored matrix
3829 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3830 
3831   Output Parameter:
3832 . X - the result matrix (dense matrix)
3833 
3834   Level: developer
3835 
3836   Note:
3837   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right-hand side matrix. User must create `Bt` in sparse compressed row
3838   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3839 
3840 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3841 @*/
3842 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3843 {
3844   PetscFunctionBegin;
3845   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3846   PetscValidType(A, 1);
3847   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3848   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3849   PetscCheckSameComm(A, 1, Bt, 2);
3850   PetscCheckSameComm(A, 1, X, 3);
3851 
3852   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3853   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);
3854   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);
3855   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");
3856   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3857   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3858   MatCheckPreallocated(A, 1);
3859 
3860   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3861   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3862   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3863   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3864   PetscFunctionReturn(PETSC_SUCCESS);
3865 }
3866 
3867 /*@
3868   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3869   $U^T*D^(1/2) 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 `MatForwardSolve`(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`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3896 @*/
3897 PetscErrorCode MatForwardSolve(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_ForwardSolve, mat, b, x, 0));
3914   PetscUseTypeMethod(mat, forwardsolve, b, x);
3915   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3916   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3917   PetscFunctionReturn(PETSC_SUCCESS);
3918 }
3919 
3920 /*@
3921   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3922   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3923 
3924   Neighbor-wise Collective
3925 
3926   Input Parameters:
3927 + mat - the factored matrix
3928 - b   - the right-hand-side vector
3929 
3930   Output Parameter:
3931 . x - the result vector
3932 
3933   Level: developer
3934 
3935   Notes:
3936   `MatSolve()` should be used for most applications, as it performs
3937   a forward solve followed by a backward solve.
3938 
3939   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3940   call `MatBackwardSolve`(A,x,x).
3941 
3942   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3943   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3944   `MatForwardSolve()` solves $U^T*D y = b$, and
3945   `MatBackwardSolve()` solves $U x = y$.
3946   Thus they do not provide a symmetric preconditioner.
3947 
3948 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3949 @*/
3950 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3951 {
3952   PetscFunctionBegin;
3953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3954   PetscValidType(mat, 1);
3955   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3956   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3957   PetscCheckSameComm(mat, 1, b, 2);
3958   PetscCheckSameComm(mat, 1, x, 3);
3959   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3960   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);
3961   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);
3962   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);
3963   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3964   MatCheckPreallocated(mat, 1);
3965 
3966   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3967   PetscUseTypeMethod(mat, backwardsolve, b, x);
3968   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3969   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3970   PetscFunctionReturn(PETSC_SUCCESS);
3971 }
3972 
3973 /*@
3974   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3975 
3976   Neighbor-wise Collective
3977 
3978   Input Parameters:
3979 + mat - the factored matrix
3980 . b   - the right-hand-side vector
3981 - y   - the vector to be added to
3982 
3983   Output Parameter:
3984 . x - the result vector
3985 
3986   Level: developer
3987 
3988   Note:
3989   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3990   call `MatSolveAdd`(A,x,y,x).
3991 
3992 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3993 @*/
3994 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3995 {
3996   PetscScalar one = 1.0;
3997   Vec         tmp;
3998 
3999   PetscFunctionBegin;
4000   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4001   PetscValidType(mat, 1);
4002   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4003   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4004   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4005   PetscCheckSameComm(mat, 1, b, 2);
4006   PetscCheckSameComm(mat, 1, y, 3);
4007   PetscCheckSameComm(mat, 1, x, 4);
4008   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4009   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);
4010   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);
4011   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);
4012   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);
4013   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);
4014   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4015   MatCheckPreallocated(mat, 1);
4016 
4017   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4018   PetscCall(VecFlag(x, mat->factorerrortype));
4019   if (mat->factorerrortype) {
4020     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4021   } else if (mat->ops->solveadd) {
4022     PetscUseTypeMethod(mat, solveadd, b, y, x);
4023   } else {
4024     /* do the solve then the add manually */
4025     if (x != y) {
4026       PetscCall(MatSolve(mat, b, x));
4027       PetscCall(VecAXPY(x, one, y));
4028     } else {
4029       PetscCall(VecDuplicate(x, &tmp));
4030       PetscCall(VecCopy(x, tmp));
4031       PetscCall(MatSolve(mat, b, x));
4032       PetscCall(VecAXPY(x, one, tmp));
4033       PetscCall(VecDestroy(&tmp));
4034     }
4035   }
4036   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4037   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4038   PetscFunctionReturn(PETSC_SUCCESS);
4039 }
4040 
4041 /*@
4042   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4043 
4044   Neighbor-wise Collective
4045 
4046   Input Parameters:
4047 + mat - the factored matrix
4048 - b   - the right-hand-side vector
4049 
4050   Output Parameter:
4051 . x - the result vector
4052 
4053   Level: developer
4054 
4055   Notes:
4056   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4057   call `MatSolveTranspose`(A,x,x).
4058 
4059   Most users should employ the `KSP` interface for linear solvers
4060   instead of working directly with matrix algebra routines such as this.
4061   See, e.g., `KSPCreate()`.
4062 
4063 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4064 @*/
4065 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4066 {
4067   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4068 
4069   PetscFunctionBegin;
4070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4071   PetscValidType(mat, 1);
4072   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4073   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4074   PetscCheckSameComm(mat, 1, b, 2);
4075   PetscCheckSameComm(mat, 1, x, 3);
4076   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4077   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);
4078   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);
4079   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4080   MatCheckPreallocated(mat, 1);
4081   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4082   PetscCall(VecFlag(x, mat->factorerrortype));
4083   if (mat->factorerrortype) {
4084     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4085   } else {
4086     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4087     PetscCall((*f)(mat, b, x));
4088   }
4089   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4090   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4091   PetscFunctionReturn(PETSC_SUCCESS);
4092 }
4093 
4094 /*@
4095   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4096   factored matrix.
4097 
4098   Neighbor-wise Collective
4099 
4100   Input Parameters:
4101 + mat - the factored matrix
4102 . b   - the right-hand-side vector
4103 - y   - the vector to be added to
4104 
4105   Output Parameter:
4106 . x - the result vector
4107 
4108   Level: developer
4109 
4110   Note:
4111   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4112   call `MatSolveTransposeAdd`(A,x,y,x).
4113 
4114 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4115 @*/
4116 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4117 {
4118   PetscScalar one = 1.0;
4119   Vec         tmp;
4120   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4121 
4122   PetscFunctionBegin;
4123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4124   PetscValidType(mat, 1);
4125   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4126   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4127   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4128   PetscCheckSameComm(mat, 1, b, 2);
4129   PetscCheckSameComm(mat, 1, y, 3);
4130   PetscCheckSameComm(mat, 1, x, 4);
4131   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4132   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);
4133   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);
4134   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);
4135   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);
4136   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4137   MatCheckPreallocated(mat, 1);
4138 
4139   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4140   PetscCall(VecFlag(x, mat->factorerrortype));
4141   if (mat->factorerrortype) {
4142     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4143   } else if (f) {
4144     PetscCall((*f)(mat, b, y, x));
4145   } else {
4146     /* do the solve then the add manually */
4147     if (x != y) {
4148       PetscCall(MatSolveTranspose(mat, b, x));
4149       PetscCall(VecAXPY(x, one, y));
4150     } else {
4151       PetscCall(VecDuplicate(x, &tmp));
4152       PetscCall(VecCopy(x, tmp));
4153       PetscCall(MatSolveTranspose(mat, b, x));
4154       PetscCall(VecAXPY(x, one, tmp));
4155       PetscCall(VecDestroy(&tmp));
4156     }
4157   }
4158   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4159   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4160   PetscFunctionReturn(PETSC_SUCCESS);
4161 }
4162 
4163 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4164 /*@
4165   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4166 
4167   Neighbor-wise Collective
4168 
4169   Input Parameters:
4170 + mat   - the matrix
4171 . b     - the right-hand side
4172 . omega - the relaxation factor
4173 . flag  - flag indicating the type of SOR (see below)
4174 . shift - diagonal shift
4175 . its   - the number of iterations
4176 - lits  - the number of local iterations
4177 
4178   Output Parameter:
4179 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4180 
4181   SOR Flags:
4182 +     `SOR_FORWARD_SWEEP` - forward SOR
4183 .     `SOR_BACKWARD_SWEEP` - backward SOR
4184 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4185 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4186 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4187 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4188 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4189 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4190   upper/lower triangular part of matrix to
4191   vector (with omega)
4192 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4193 
4194   Level: developer
4195 
4196   Notes:
4197   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4198   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4199   on each processor.
4200 
4201   Application programmers will not generally use `MatSOR()` directly,
4202   but instead will employ the `KSP`/`PC` interface.
4203 
4204   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4205 
4206   Most users should employ the `KSP` interface for linear solvers
4207   instead of working directly with matrix algebra routines such as this.
4208   See, e.g., `KSPCreate()`.
4209 
4210   Vectors `x` and `b` CANNOT be the same
4211 
4212   The flags are implemented as bitwise inclusive or operations.
4213   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4214   to specify a zero initial guess for SSOR.
4215 
4216   Developer Note:
4217   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4218 
4219 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4220 @*/
4221 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4222 {
4223   PetscFunctionBegin;
4224   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4225   PetscValidType(mat, 1);
4226   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4227   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4228   PetscCheckSameComm(mat, 1, b, 2);
4229   PetscCheckSameComm(mat, 1, x, 8);
4230   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4231   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4232   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);
4233   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);
4234   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);
4235   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4236   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4237   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4238 
4239   MatCheckPreallocated(mat, 1);
4240   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4241   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4242   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4243   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4244   PetscFunctionReturn(PETSC_SUCCESS);
4245 }
4246 
4247 /*
4248       Default matrix copy routine.
4249 */
4250 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4251 {
4252   PetscInt           i, rstart = 0, rend = 0, nz;
4253   const PetscInt    *cwork;
4254   const PetscScalar *vwork;
4255 
4256   PetscFunctionBegin;
4257   if (B->assembled) PetscCall(MatZeroEntries(B));
4258   if (str == SAME_NONZERO_PATTERN) {
4259     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4260     for (i = rstart; i < rend; i++) {
4261       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4262       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4263       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4264     }
4265   } else {
4266     PetscCall(MatAYPX(B, 0.0, A, str));
4267   }
4268   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4269   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4270   PetscFunctionReturn(PETSC_SUCCESS);
4271 }
4272 
4273 /*@
4274   MatCopy - Copies a matrix to another matrix.
4275 
4276   Collective
4277 
4278   Input Parameters:
4279 + A   - the matrix
4280 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4281 
4282   Output Parameter:
4283 . B - where the copy is put
4284 
4285   Level: intermediate
4286 
4287   Notes:
4288   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4289 
4290   `MatCopy()` copies the matrix entries of a matrix to another existing
4291   matrix (after first zeroing the second matrix).  A related routine is
4292   `MatConvert()`, which first creates a new matrix and then copies the data.
4293 
4294 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4295 @*/
4296 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4297 {
4298   PetscInt i;
4299 
4300   PetscFunctionBegin;
4301   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4302   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4303   PetscValidType(A, 1);
4304   PetscValidType(B, 2);
4305   PetscCheckSameComm(A, 1, B, 2);
4306   MatCheckPreallocated(B, 2);
4307   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4308   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4309   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,
4310              A->cmap->N, B->cmap->N);
4311   MatCheckPreallocated(A, 1);
4312   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4313 
4314   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4315   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4316   else PetscCall(MatCopy_Basic(A, B, str));
4317 
4318   B->stencil.dim = A->stencil.dim;
4319   B->stencil.noc = A->stencil.noc;
4320   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4321     B->stencil.dims[i]   = A->stencil.dims[i];
4322     B->stencil.starts[i] = A->stencil.starts[i];
4323   }
4324 
4325   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4326   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4327   PetscFunctionReturn(PETSC_SUCCESS);
4328 }
4329 
4330 /*@
4331   MatConvert - Converts a matrix to another matrix, either of the same
4332   or different type.
4333 
4334   Collective
4335 
4336   Input Parameters:
4337 + mat     - the matrix
4338 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4339             same type as the original matrix.
4340 - reuse   - denotes if the destination matrix is to be created or reused.
4341             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
4342             `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).
4343 
4344   Output Parameter:
4345 . M - pointer to place new matrix
4346 
4347   Level: intermediate
4348 
4349   Notes:
4350   `MatConvert()` first creates a new matrix and then copies the data from
4351   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4352   entries of one matrix to another already existing matrix context.
4353 
4354   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4355   the MPI communicator of the generated matrix is always the same as the communicator
4356   of the input matrix.
4357 
4358 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4359 @*/
4360 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4361 {
4362   PetscBool  sametype, issame, flg;
4363   PetscBool3 issymmetric, ishermitian;
4364   char       convname[256], mtype[256];
4365   Mat        B;
4366 
4367   PetscFunctionBegin;
4368   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4369   PetscValidType(mat, 1);
4370   PetscAssertPointer(M, 4);
4371   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4372   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4373   MatCheckPreallocated(mat, 1);
4374 
4375   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4376   if (flg) newtype = mtype;
4377 
4378   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4379   PetscCall(PetscStrcmp(newtype, "same", &issame));
4380   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4381   if (reuse == MAT_REUSE_MATRIX) {
4382     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4383     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4384   }
4385 
4386   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4387     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4388     PetscFunctionReturn(PETSC_SUCCESS);
4389   }
4390 
4391   /* Cache Mat options because some converters use MatHeaderReplace  */
4392   issymmetric = mat->symmetric;
4393   ishermitian = mat->hermitian;
4394 
4395   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4396     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4397     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4398   } else {
4399     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4400     const char *prefix[3]                                 = {"seq", "mpi", ""};
4401     PetscInt    i;
4402     /*
4403        Order of precedence:
4404        0) See if newtype is a superclass of the current matrix.
4405        1) See if a specialized converter is known to the current matrix.
4406        2) See if a specialized converter is known to the desired matrix class.
4407        3) See if a good general converter is registered for the desired class
4408           (as of 6/27/03 only MATMPIADJ falls into this category).
4409        4) See if a good general converter is known for the current matrix.
4410        5) Use a really basic converter.
4411     */
4412 
4413     /* 0) See if newtype is a superclass of the current matrix.
4414           i.e mat is mpiaij and newtype is aij */
4415     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4416       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4417       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4418       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4419       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4420       if (flg) {
4421         if (reuse == MAT_INPLACE_MATRIX) {
4422           PetscCall(PetscInfo(mat, "Early return\n"));
4423           PetscFunctionReturn(PETSC_SUCCESS);
4424         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4425           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4426           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4427           PetscFunctionReturn(PETSC_SUCCESS);
4428         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4429           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4430           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4431           PetscFunctionReturn(PETSC_SUCCESS);
4432         }
4433       }
4434     }
4435     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4436     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4437       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4438       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4439       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4440       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4441       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4442       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4443       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4444       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4445       if (conv) goto foundconv;
4446     }
4447 
4448     /* 2)  See if a specialized converter is known to the desired matrix class. */
4449     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4450     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4451     PetscCall(MatSetType(B, newtype));
4452     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4453       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4454       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4455       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4456       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4457       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4458       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4459       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4460       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4461       if (conv) {
4462         PetscCall(MatDestroy(&B));
4463         goto foundconv;
4464       }
4465     }
4466 
4467     /* 3) See if a good general converter is registered for the desired class */
4468     conv = B->ops->convertfrom;
4469     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4470     PetscCall(MatDestroy(&B));
4471     if (conv) goto foundconv;
4472 
4473     /* 4) See if a good general converter is known for the current matrix */
4474     if (mat->ops->convert) conv = mat->ops->convert;
4475     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4476     if (conv) goto foundconv;
4477 
4478     /* 5) Use a really basic converter. */
4479     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4480     conv = MatConvert_Basic;
4481 
4482   foundconv:
4483     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4484     PetscCall((*conv)(mat, newtype, reuse, M));
4485     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4486       /* the block sizes must be same if the mappings are copied over */
4487       (*M)->rmap->bs = mat->rmap->bs;
4488       (*M)->cmap->bs = mat->cmap->bs;
4489       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4490       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4491       (*M)->rmap->mapping = mat->rmap->mapping;
4492       (*M)->cmap->mapping = mat->cmap->mapping;
4493     }
4494     (*M)->stencil.dim = mat->stencil.dim;
4495     (*M)->stencil.noc = mat->stencil.noc;
4496     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4497       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4498       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4499     }
4500     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4501   }
4502   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4503 
4504   /* Copy Mat options */
4505   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4506   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4507   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4508   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4509   PetscFunctionReturn(PETSC_SUCCESS);
4510 }
4511 
4512 /*@
4513   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4514 
4515   Not Collective
4516 
4517   Input Parameter:
4518 . mat - the matrix, must be a factored matrix
4519 
4520   Output Parameter:
4521 . type - the string name of the package (do not free this string)
4522 
4523   Level: intermediate
4524 
4525 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4526 @*/
4527 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4528 {
4529   PetscErrorCode (*conv)(Mat, MatSolverType *);
4530 
4531   PetscFunctionBegin;
4532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4533   PetscValidType(mat, 1);
4534   PetscAssertPointer(type, 2);
4535   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4536   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4537   if (conv) PetscCall((*conv)(mat, type));
4538   else *type = MATSOLVERPETSC;
4539   PetscFunctionReturn(PETSC_SUCCESS);
4540 }
4541 
4542 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4543 struct _MatSolverTypeForSpecifcType {
4544   MatType mtype;
4545   /* no entry for MAT_FACTOR_NONE */
4546   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4547   MatSolverTypeForSpecifcType next;
4548 };
4549 
4550 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4551 struct _MatSolverTypeHolder {
4552   char                       *name;
4553   MatSolverTypeForSpecifcType handlers;
4554   MatSolverTypeHolder         next;
4555 };
4556 
4557 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4558 
4559 /*@C
4560   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4561 
4562   Logically Collective, No Fortran Support
4563 
4564   Input Parameters:
4565 + package      - name of the package, for example `petsc` or `superlu`
4566 . mtype        - the matrix type that works with this package
4567 . ftype        - the type of factorization supported by the package
4568 - createfactor - routine that will create the factored matrix ready to be used
4569 
4570   Level: developer
4571 
4572 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4573   `MatGetFactor()`
4574 @*/
4575 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4576 {
4577   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4578   PetscBool                   flg;
4579   MatSolverTypeForSpecifcType inext, iprev = NULL;
4580 
4581   PetscFunctionBegin;
4582   PetscCall(MatInitializePackage());
4583   if (!next) {
4584     PetscCall(PetscNew(&MatSolverTypeHolders));
4585     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4586     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4587     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4588     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4589     PetscFunctionReturn(PETSC_SUCCESS);
4590   }
4591   while (next) {
4592     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4593     if (flg) {
4594       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4595       inext = next->handlers;
4596       while (inext) {
4597         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4598         if (flg) {
4599           inext->createfactor[(int)ftype - 1] = createfactor;
4600           PetscFunctionReturn(PETSC_SUCCESS);
4601         }
4602         iprev = inext;
4603         inext = inext->next;
4604       }
4605       PetscCall(PetscNew(&iprev->next));
4606       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4607       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4608       PetscFunctionReturn(PETSC_SUCCESS);
4609     }
4610     prev = next;
4611     next = next->next;
4612   }
4613   PetscCall(PetscNew(&prev->next));
4614   PetscCall(PetscStrallocpy(package, &prev->next->name));
4615   PetscCall(PetscNew(&prev->next->handlers));
4616   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4617   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4618   PetscFunctionReturn(PETSC_SUCCESS);
4619 }
4620 
4621 /*@C
4622   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4623 
4624   Input Parameters:
4625 + type  - name of the package, for example `petsc` or `superlu`, if this is 'NULL', then the first result that satisfies the other criteria is returned
4626 . ftype - the type of factorization supported by the type
4627 - mtype - the matrix type that works with this type
4628 
4629   Output Parameters:
4630 + foundtype    - `PETSC_TRUE` if the type was registered
4631 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4632 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4633 
4634   Calling sequence of `createfactor`:
4635 + A     - the matrix providing the factor matrix
4636 . ftype - the `MatFactorType` of the factor requested
4637 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4638 
4639   Level: developer
4640 
4641   Note:
4642   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4643   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4644   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4645 
4646 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4647           `MatInitializePackage()`
4648 @*/
4649 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4650 {
4651   MatSolverTypeHolder         next = MatSolverTypeHolders;
4652   PetscBool                   flg;
4653   MatSolverTypeForSpecifcType inext;
4654 
4655   PetscFunctionBegin;
4656   if (foundtype) *foundtype = PETSC_FALSE;
4657   if (foundmtype) *foundmtype = PETSC_FALSE;
4658   if (createfactor) *createfactor = NULL;
4659 
4660   if (type) {
4661     while (next) {
4662       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4663       if (flg) {
4664         if (foundtype) *foundtype = PETSC_TRUE;
4665         inext = next->handlers;
4666         while (inext) {
4667           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4668           if (flg) {
4669             if (foundmtype) *foundmtype = PETSC_TRUE;
4670             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4671             PetscFunctionReturn(PETSC_SUCCESS);
4672           }
4673           inext = inext->next;
4674         }
4675       }
4676       next = next->next;
4677     }
4678   } else {
4679     while (next) {
4680       inext = next->handlers;
4681       while (inext) {
4682         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4683         if (flg && inext->createfactor[(int)ftype - 1]) {
4684           if (foundtype) *foundtype = PETSC_TRUE;
4685           if (foundmtype) *foundmtype = PETSC_TRUE;
4686           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4687           PetscFunctionReturn(PETSC_SUCCESS);
4688         }
4689         inext = inext->next;
4690       }
4691       next = next->next;
4692     }
4693     /* try with base classes inext->mtype */
4694     next = MatSolverTypeHolders;
4695     while (next) {
4696       inext = next->handlers;
4697       while (inext) {
4698         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4699         if (flg && inext->createfactor[(int)ftype - 1]) {
4700           if (foundtype) *foundtype = PETSC_TRUE;
4701           if (foundmtype) *foundmtype = PETSC_TRUE;
4702           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4703           PetscFunctionReturn(PETSC_SUCCESS);
4704         }
4705         inext = inext->next;
4706       }
4707       next = next->next;
4708     }
4709   }
4710   PetscFunctionReturn(PETSC_SUCCESS);
4711 }
4712 
4713 PetscErrorCode MatSolverTypeDestroy(void)
4714 {
4715   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4716   MatSolverTypeForSpecifcType inext, iprev;
4717 
4718   PetscFunctionBegin;
4719   while (next) {
4720     PetscCall(PetscFree(next->name));
4721     inext = next->handlers;
4722     while (inext) {
4723       PetscCall(PetscFree(inext->mtype));
4724       iprev = inext;
4725       inext = inext->next;
4726       PetscCall(PetscFree(iprev));
4727     }
4728     prev = next;
4729     next = next->next;
4730     PetscCall(PetscFree(prev));
4731   }
4732   MatSolverTypeHolders = NULL;
4733   PetscFunctionReturn(PETSC_SUCCESS);
4734 }
4735 
4736 /*@
4737   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4738 
4739   Logically Collective
4740 
4741   Input Parameter:
4742 . mat - the matrix
4743 
4744   Output Parameter:
4745 . flg - `PETSC_TRUE` if uses the ordering
4746 
4747   Level: developer
4748 
4749   Note:
4750   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4751   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4752 
4753 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4754 @*/
4755 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4756 {
4757   PetscFunctionBegin;
4758   *flg = mat->canuseordering;
4759   PetscFunctionReturn(PETSC_SUCCESS);
4760 }
4761 
4762 /*@
4763   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4764 
4765   Logically Collective
4766 
4767   Input Parameters:
4768 + mat   - the matrix obtained with `MatGetFactor()`
4769 - ftype - the factorization type to be used
4770 
4771   Output Parameter:
4772 . otype - the preferred ordering type
4773 
4774   Level: developer
4775 
4776 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4777 @*/
4778 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4779 {
4780   PetscFunctionBegin;
4781   *otype = mat->preferredordering[ftype];
4782   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4783   PetscFunctionReturn(PETSC_SUCCESS);
4784 }
4785 
4786 /*@
4787   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4788 
4789   Collective
4790 
4791   Input Parameters:
4792 + mat   - the matrix
4793 . type  - name of solver type, for example, `superlu`, `petsc` (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies
4794           the other criteria is returned
4795 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4796 
4797   Output Parameter:
4798 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4799 
4800   Options Database Keys:
4801 + -pc_factor_mat_solver_type <type>    - choose the type at run time. When using `KSP` solvers
4802 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device
4803 - -pc_factor_mat_solve_on_host <bool>  - do mat solve on host (with device matrices). Default is doing it on device
4804 
4805   Level: intermediate
4806 
4807   Notes:
4808   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4809   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4810 
4811   Users usually access the factorization solvers via `KSP`
4812 
4813   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4814   such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir
4815 
4816   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4817   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4818   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4819 
4820   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4821   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4822   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4823 
4824   Developer Note:
4825   This should actually be called `MatCreateFactor()` since it creates a new factor object
4826 
4827 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4828           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4829           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4830 @*/
4831 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4832 {
4833   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4834   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4835 
4836   PetscFunctionBegin;
4837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4838   PetscValidType(mat, 1);
4839 
4840   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4841   MatCheckPreallocated(mat, 1);
4842 
4843   PetscCall(MatIsShell(mat, &shell));
4844   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4845   if (hasop) {
4846     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4847     PetscFunctionReturn(PETSC_SUCCESS);
4848   }
4849 
4850   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4851   if (!foundtype) {
4852     if (type) {
4853       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],
4854               ((PetscObject)mat)->type_name, type);
4855     } else {
4856       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);
4857     }
4858   }
4859   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4860   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);
4861 
4862   PetscCall((*conv)(mat, ftype, f));
4863   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4864   PetscFunctionReturn(PETSC_SUCCESS);
4865 }
4866 
4867 /*@
4868   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4869 
4870   Not Collective
4871 
4872   Input Parameters:
4873 + mat   - the matrix
4874 . type  - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default)
4875 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4876 
4877   Output Parameter:
4878 . flg - PETSC_TRUE if the factorization is available
4879 
4880   Level: intermediate
4881 
4882   Notes:
4883   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4884   such as pastix, superlu, mumps etc.
4885 
4886   PETSc must have been ./configure to use the external solver, using the option --download-package
4887 
4888   Developer Note:
4889   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4890 
4891 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4892           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4893 @*/
4894 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4895 {
4896   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4897 
4898   PetscFunctionBegin;
4899   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4900   PetscAssertPointer(flg, 4);
4901 
4902   *flg = PETSC_FALSE;
4903   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4904 
4905   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4906   MatCheckPreallocated(mat, 1);
4907 
4908   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4909   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4910   PetscFunctionReturn(PETSC_SUCCESS);
4911 }
4912 
4913 /*@
4914   MatDuplicate - Duplicates a matrix including the non-zero structure.
4915 
4916   Collective
4917 
4918   Input Parameters:
4919 + mat - the matrix
4920 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4921         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4922 
4923   Output Parameter:
4924 . M - pointer to place new matrix
4925 
4926   Level: intermediate
4927 
4928   Notes:
4929   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4930 
4931   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4932 
4933   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.
4934 
4935   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4936   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4937   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4938 
4939 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4940 @*/
4941 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4942 {
4943   Mat         B;
4944   VecType     vtype;
4945   PetscInt    i;
4946   PetscObject dm, container_h, container_d;
4947   void (*viewf)(void);
4948 
4949   PetscFunctionBegin;
4950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4951   PetscValidType(mat, 1);
4952   PetscAssertPointer(M, 3);
4953   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4954   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4955   MatCheckPreallocated(mat, 1);
4956 
4957   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4958   PetscUseTypeMethod(mat, duplicate, op, M);
4959   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4960   B = *M;
4961 
4962   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4963   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4964   PetscCall(MatGetVecType(mat, &vtype));
4965   PetscCall(MatSetVecType(B, vtype));
4966 
4967   B->stencil.dim = mat->stencil.dim;
4968   B->stencil.noc = mat->stencil.noc;
4969   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4970     B->stencil.dims[i]   = mat->stencil.dims[i];
4971     B->stencil.starts[i] = mat->stencil.starts[i];
4972   }
4973 
4974   B->nooffproczerorows = mat->nooffproczerorows;
4975   B->nooffprocentries  = mat->nooffprocentries;
4976 
4977   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4978   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4979   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4980   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4981   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4982   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4983   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4984   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4985   PetscFunctionReturn(PETSC_SUCCESS);
4986 }
4987 
4988 /*@
4989   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4990 
4991   Logically Collective
4992 
4993   Input Parameter:
4994 . mat - the matrix
4995 
4996   Output Parameter:
4997 . v - the diagonal of the matrix
4998 
4999   Level: intermediate
5000 
5001   Note:
5002   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5003   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5004   is larger than `ndiag`, the values of the remaining entries are unspecified.
5005 
5006   Currently only correct in parallel for square matrices.
5007 
5008 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5009 @*/
5010 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5011 {
5012   PetscFunctionBegin;
5013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5014   PetscValidType(mat, 1);
5015   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5016   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5017   MatCheckPreallocated(mat, 1);
5018   if (PetscDefined(USE_DEBUG)) {
5019     PetscInt nv, row, col, ndiag;
5020 
5021     PetscCall(VecGetLocalSize(v, &nv));
5022     PetscCall(MatGetLocalSize(mat, &row, &col));
5023     ndiag = PetscMin(row, col);
5024     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);
5025   }
5026 
5027   PetscUseTypeMethod(mat, getdiagonal, v);
5028   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5029   PetscFunctionReturn(PETSC_SUCCESS);
5030 }
5031 
5032 /*@
5033   MatGetRowMin - Gets the minimum value (of the real part) of each
5034   row of the matrix
5035 
5036   Logically Collective
5037 
5038   Input Parameter:
5039 . mat - the matrix
5040 
5041   Output Parameters:
5042 + v   - the vector for storing the maximums
5043 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5044 
5045   Level: intermediate
5046 
5047   Note:
5048   The result of this call are the same as if one converted the matrix to dense format
5049   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5050 
5051   This code is only implemented for a couple of matrix formats.
5052 
5053 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5054           `MatGetRowMax()`
5055 @*/
5056 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5057 {
5058   PetscFunctionBegin;
5059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5060   PetscValidType(mat, 1);
5061   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5062   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5063 
5064   if (!mat->cmap->N) {
5065     PetscCall(VecSet(v, PETSC_MAX_REAL));
5066     if (idx) {
5067       PetscInt i, m = mat->rmap->n;
5068       for (i = 0; i < m; i++) idx[i] = -1;
5069     }
5070   } else {
5071     MatCheckPreallocated(mat, 1);
5072   }
5073   PetscUseTypeMethod(mat, getrowmin, v, idx);
5074   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5075   PetscFunctionReturn(PETSC_SUCCESS);
5076 }
5077 
5078 /*@
5079   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5080   row of the matrix
5081 
5082   Logically Collective
5083 
5084   Input Parameter:
5085 . mat - the matrix
5086 
5087   Output Parameters:
5088 + v   - the vector for storing the minimums
5089 - idx - the indices of the column found for each row (or `NULL` if not needed)
5090 
5091   Level: intermediate
5092 
5093   Notes:
5094   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5095   row is 0 (the first column).
5096 
5097   This code is only implemented for a couple of matrix formats.
5098 
5099 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5100 @*/
5101 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5102 {
5103   PetscFunctionBegin;
5104   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5105   PetscValidType(mat, 1);
5106   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5107   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5108   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5109 
5110   if (!mat->cmap->N) {
5111     PetscCall(VecSet(v, 0.0));
5112     if (idx) {
5113       PetscInt i, m = mat->rmap->n;
5114       for (i = 0; i < m; i++) idx[i] = -1;
5115     }
5116   } else {
5117     MatCheckPreallocated(mat, 1);
5118     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5119     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5120   }
5121   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5122   PetscFunctionReturn(PETSC_SUCCESS);
5123 }
5124 
5125 /*@
5126   MatGetRowMax - Gets the maximum value (of the real part) of each
5127   row of the matrix
5128 
5129   Logically Collective
5130 
5131   Input Parameter:
5132 . mat - the matrix
5133 
5134   Output Parameters:
5135 + v   - the vector for storing the maximums
5136 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5137 
5138   Level: intermediate
5139 
5140   Notes:
5141   The result of this call are the same as if one converted the matrix to dense format
5142   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5143 
5144   This code is only implemented for a couple of matrix formats.
5145 
5146 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5147 @*/
5148 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5149 {
5150   PetscFunctionBegin;
5151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5152   PetscValidType(mat, 1);
5153   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5154   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5155 
5156   if (!mat->cmap->N) {
5157     PetscCall(VecSet(v, PETSC_MIN_REAL));
5158     if (idx) {
5159       PetscInt i, m = mat->rmap->n;
5160       for (i = 0; i < m; i++) idx[i] = -1;
5161     }
5162   } else {
5163     MatCheckPreallocated(mat, 1);
5164     PetscUseTypeMethod(mat, getrowmax, v, idx);
5165   }
5166   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5167   PetscFunctionReturn(PETSC_SUCCESS);
5168 }
5169 
5170 /*@
5171   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5172   row of the matrix
5173 
5174   Logically Collective
5175 
5176   Input Parameter:
5177 . mat - the matrix
5178 
5179   Output Parameters:
5180 + v   - the vector for storing the maximums
5181 - idx - the indices of the column found for each row (or `NULL` if not needed)
5182 
5183   Level: intermediate
5184 
5185   Notes:
5186   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5187   row is 0 (the first column).
5188 
5189   This code is only implemented for a couple of matrix formats.
5190 
5191 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5192 @*/
5193 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5194 {
5195   PetscFunctionBegin;
5196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5197   PetscValidType(mat, 1);
5198   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5199   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5200 
5201   if (!mat->cmap->N) {
5202     PetscCall(VecSet(v, 0.0));
5203     if (idx) {
5204       PetscInt i, m = mat->rmap->n;
5205       for (i = 0; i < m; i++) idx[i] = -1;
5206     }
5207   } else {
5208     MatCheckPreallocated(mat, 1);
5209     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5210     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5211   }
5212   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5213   PetscFunctionReturn(PETSC_SUCCESS);
5214 }
5215 
5216 /*@
5217   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5218 
5219   Logically Collective
5220 
5221   Input Parameter:
5222 . mat - the matrix
5223 
5224   Output Parameter:
5225 . v - the vector for storing the sum
5226 
5227   Level: intermediate
5228 
5229   This code is only implemented for a couple of matrix formats.
5230 
5231 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5232 @*/
5233 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5234 {
5235   PetscFunctionBegin;
5236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5237   PetscValidType(mat, 1);
5238   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5239   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5240 
5241   if (!mat->cmap->N) {
5242     PetscCall(VecSet(v, 0.0));
5243   } else {
5244     MatCheckPreallocated(mat, 1);
5245     PetscUseTypeMethod(mat, getrowsumabs, v);
5246   }
5247   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5248   PetscFunctionReturn(PETSC_SUCCESS);
5249 }
5250 
5251 /*@
5252   MatGetRowSum - Gets the sum of each row of the matrix
5253 
5254   Logically or Neighborhood Collective
5255 
5256   Input Parameter:
5257 . mat - the matrix
5258 
5259   Output Parameter:
5260 . v - the vector for storing the sum of rows
5261 
5262   Level: intermediate
5263 
5264   Note:
5265   This code is slow since it is not currently specialized for different formats
5266 
5267 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5268 @*/
5269 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5270 {
5271   Vec ones;
5272 
5273   PetscFunctionBegin;
5274   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5275   PetscValidType(mat, 1);
5276   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5277   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5278   MatCheckPreallocated(mat, 1);
5279   PetscCall(MatCreateVecs(mat, &ones, NULL));
5280   PetscCall(VecSet(ones, 1.));
5281   PetscCall(MatMult(mat, ones, v));
5282   PetscCall(VecDestroy(&ones));
5283   PetscFunctionReturn(PETSC_SUCCESS);
5284 }
5285 
5286 /*@
5287   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5288   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5289 
5290   Collective
5291 
5292   Input Parameter:
5293 . mat - the matrix to provide the transpose
5294 
5295   Output Parameter:
5296 . 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
5297 
5298   Level: advanced
5299 
5300   Note:
5301   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
5302   routine allows bypassing that call.
5303 
5304 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5305 @*/
5306 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5307 {
5308   MatParentState *rb = NULL;
5309 
5310   PetscFunctionBegin;
5311   PetscCall(PetscNew(&rb));
5312   rb->id    = ((PetscObject)mat)->id;
5313   rb->state = 0;
5314   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5315   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5316   PetscFunctionReturn(PETSC_SUCCESS);
5317 }
5318 
5319 /*@
5320   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5321 
5322   Collective
5323 
5324   Input Parameters:
5325 + mat   - the matrix to transpose
5326 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5327 
5328   Output Parameter:
5329 . B - the transpose of the matrix
5330 
5331   Level: intermediate
5332 
5333   Notes:
5334   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5335 
5336   `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the
5337   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5338 
5339   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.
5340 
5341   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5342   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5343 
5344   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5345 
5346   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5347 
5348 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5349           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5350 @*/
5351 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5352 {
5353   PetscContainer  rB = NULL;
5354   MatParentState *rb = NULL;
5355 
5356   PetscFunctionBegin;
5357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5358   PetscValidType(mat, 1);
5359   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5360   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5361   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5362   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5363   MatCheckPreallocated(mat, 1);
5364   if (reuse == MAT_REUSE_MATRIX) {
5365     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5366     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5367     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5368     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5369     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5370   }
5371 
5372   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5373   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5374     PetscUseTypeMethod(mat, transpose, reuse, B);
5375     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5376   }
5377   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5378 
5379   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5380   if (reuse != MAT_INPLACE_MATRIX) {
5381     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5382     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5383     rb->state        = ((PetscObject)mat)->state;
5384     rb->nonzerostate = mat->nonzerostate;
5385   }
5386   PetscFunctionReturn(PETSC_SUCCESS);
5387 }
5388 
5389 /*@
5390   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5391 
5392   Collective
5393 
5394   Input Parameter:
5395 . A - the matrix to transpose
5396 
5397   Output Parameter:
5398 . 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
5399       numerical portion.
5400 
5401   Level: intermediate
5402 
5403   Note:
5404   This is not supported for many matrix types, use `MatTranspose()` in those cases
5405 
5406 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5407 @*/
5408 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5409 {
5410   PetscFunctionBegin;
5411   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5412   PetscValidType(A, 1);
5413   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5414   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5415   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5416   PetscUseTypeMethod(A, transposesymbolic, B);
5417   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5418 
5419   PetscCall(MatTransposeSetPrecursor(A, *B));
5420   PetscFunctionReturn(PETSC_SUCCESS);
5421 }
5422 
5423 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5424 {
5425   PetscContainer  rB;
5426   MatParentState *rb;
5427 
5428   PetscFunctionBegin;
5429   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5430   PetscValidType(A, 1);
5431   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5432   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5433   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5434   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5435   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5436   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5437   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5438   PetscFunctionReturn(PETSC_SUCCESS);
5439 }
5440 
5441 /*@
5442   MatIsTranspose - Test whether a matrix is another one's transpose,
5443   or its own, in which case it tests symmetry.
5444 
5445   Collective
5446 
5447   Input Parameters:
5448 + A   - the matrix to test
5449 . B   - the matrix to test against, this can equal the first parameter
5450 - tol - tolerance, differences between entries smaller than this are counted as zero
5451 
5452   Output Parameter:
5453 . flg - the result
5454 
5455   Level: intermediate
5456 
5457   Notes:
5458   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5459   test involves parallel copies of the block off-diagonal parts of the matrix.
5460 
5461 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5462 @*/
5463 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5464 {
5465   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5466 
5467   PetscFunctionBegin;
5468   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5469   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5470   PetscAssertPointer(flg, 4);
5471   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5472   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5473   *flg = PETSC_FALSE;
5474   if (f && g) {
5475     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5476     PetscCall((*f)(A, B, tol, flg));
5477   } else {
5478     MatType mattype;
5479 
5480     PetscCall(MatGetType(f ? B : A, &mattype));
5481     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5488 
5489   Collective
5490 
5491   Input Parameters:
5492 + mat   - the matrix to transpose and complex conjugate
5493 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5494 
5495   Output Parameter:
5496 . B - the Hermitian transpose
5497 
5498   Level: intermediate
5499 
5500 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5501 @*/
5502 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5503 {
5504   PetscFunctionBegin;
5505   PetscCall(MatTranspose(mat, reuse, B));
5506 #if defined(PETSC_USE_COMPLEX)
5507   PetscCall(MatConjugate(*B));
5508 #endif
5509   PetscFunctionReturn(PETSC_SUCCESS);
5510 }
5511 
5512 /*@
5513   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5514 
5515   Collective
5516 
5517   Input Parameters:
5518 + A   - the matrix to test
5519 . B   - the matrix to test against, this can equal the first parameter
5520 - tol - tolerance, differences between entries smaller than this are counted as zero
5521 
5522   Output Parameter:
5523 . flg - the result
5524 
5525   Level: intermediate
5526 
5527   Notes:
5528   Only available for `MATAIJ` matrices.
5529 
5530   The sequential algorithm
5531   has a running time of the order of the number of nonzeros; the parallel
5532   test involves parallel copies of the block off-diagonal parts of the matrix.
5533 
5534 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5535 @*/
5536 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5537 {
5538   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5539 
5540   PetscFunctionBegin;
5541   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5542   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5543   PetscAssertPointer(flg, 4);
5544   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5545   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5546   if (f && g) {
5547     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5548     PetscCall((*f)(A, B, tol, flg));
5549   }
5550   PetscFunctionReturn(PETSC_SUCCESS);
5551 }
5552 
5553 /*@
5554   MatPermute - Creates a new matrix with rows and columns permuted from the
5555   original.
5556 
5557   Collective
5558 
5559   Input Parameters:
5560 + mat - the matrix to permute
5561 . row - row permutation, each processor supplies only the permutation for its rows
5562 - col - column permutation, each processor supplies only the permutation for its columns
5563 
5564   Output Parameter:
5565 . B - the permuted matrix
5566 
5567   Level: advanced
5568 
5569   Note:
5570   The index sets map from row/col of permuted matrix to row/col of original matrix.
5571   The index sets should be on the same communicator as mat and have the same local sizes.
5572 
5573   Developer Note:
5574   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5575   exploit the fact that row and col are permutations, consider implementing the
5576   more general `MatCreateSubMatrix()` instead.
5577 
5578 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5579 @*/
5580 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5581 {
5582   PetscFunctionBegin;
5583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5584   PetscValidType(mat, 1);
5585   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5586   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5587   PetscAssertPointer(B, 4);
5588   PetscCheckSameComm(mat, 1, row, 2);
5589   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5592   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5593   MatCheckPreallocated(mat, 1);
5594 
5595   if (mat->ops->permute) {
5596     PetscUseTypeMethod(mat, permute, row, col, B);
5597     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5598   } else {
5599     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5600   }
5601   PetscFunctionReturn(PETSC_SUCCESS);
5602 }
5603 
5604 /*@
5605   MatEqual - Compares two matrices.
5606 
5607   Collective
5608 
5609   Input Parameters:
5610 + A - the first matrix
5611 - B - the second matrix
5612 
5613   Output Parameter:
5614 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5615 
5616   Level: intermediate
5617 
5618   Note:
5619   If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product
5620   using several randomly created vectors, see `MatMultEqual()`.
5621 
5622 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5623 @*/
5624 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5625 {
5626   PetscFunctionBegin;
5627   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5628   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5629   PetscValidType(A, 1);
5630   PetscValidType(B, 2);
5631   PetscAssertPointer(flg, 3);
5632   PetscCheckSameComm(A, 1, B, 2);
5633   MatCheckPreallocated(A, 1);
5634   MatCheckPreallocated(B, 2);
5635   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5636   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5637   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,
5638              B->cmap->N);
5639   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5640     PetscUseTypeMethod(A, equal, B, flg);
5641   } else {
5642     PetscCall(MatMultEqual(A, B, 10, flg));
5643   }
5644   PetscFunctionReturn(PETSC_SUCCESS);
5645 }
5646 
5647 /*@
5648   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5649   matrices that are stored as vectors.  Either of the two scaling
5650   matrices can be `NULL`.
5651 
5652   Collective
5653 
5654   Input Parameters:
5655 + mat - the matrix to be scaled
5656 . l   - the left scaling vector (or `NULL`)
5657 - r   - the right scaling vector (or `NULL`)
5658 
5659   Level: intermediate
5660 
5661   Note:
5662   `MatDiagonalScale()` computes $A = LAR$, where
5663   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5664   The L scales the rows of the matrix, the R scales the columns of the matrix.
5665 
5666 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5667 @*/
5668 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5669 {
5670   PetscFunctionBegin;
5671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5672   PetscValidType(mat, 1);
5673   if (l) {
5674     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5675     PetscCheckSameComm(mat, 1, l, 2);
5676   }
5677   if (r) {
5678     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5679     PetscCheckSameComm(mat, 1, r, 3);
5680   }
5681   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5682   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5683   MatCheckPreallocated(mat, 1);
5684   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5685 
5686   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5687   PetscUseTypeMethod(mat, diagonalscale, l, r);
5688   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5689   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5690   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5691   PetscFunctionReturn(PETSC_SUCCESS);
5692 }
5693 
5694 /*@
5695   MatScale - Scales all elements of a matrix by a given number.
5696 
5697   Logically Collective
5698 
5699   Input Parameters:
5700 + mat - the matrix to be scaled
5701 - a   - the scaling value
5702 
5703   Level: intermediate
5704 
5705 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5706 @*/
5707 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5708 {
5709   PetscFunctionBegin;
5710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5711   PetscValidType(mat, 1);
5712   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5713   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5714   PetscValidLogicalCollectiveScalar(mat, a, 2);
5715   MatCheckPreallocated(mat, 1);
5716 
5717   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5718   if (a != (PetscScalar)1.0) {
5719     PetscUseTypeMethod(mat, scale, a);
5720     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5721   }
5722   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5723   PetscFunctionReturn(PETSC_SUCCESS);
5724 }
5725 
5726 /*@
5727   MatNorm - Calculates various norms of a matrix.
5728 
5729   Collective
5730 
5731   Input Parameters:
5732 + mat  - the matrix
5733 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5734 
5735   Output Parameter:
5736 . nrm - the resulting norm
5737 
5738   Level: intermediate
5739 
5740 .seealso: [](ch_matrices), `Mat`
5741 @*/
5742 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5743 {
5744   PetscFunctionBegin;
5745   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5746   PetscValidType(mat, 1);
5747   PetscAssertPointer(nrm, 3);
5748 
5749   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5750   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5751   MatCheckPreallocated(mat, 1);
5752 
5753   PetscUseTypeMethod(mat, norm, type, nrm);
5754   PetscFunctionReturn(PETSC_SUCCESS);
5755 }
5756 
5757 /*
5758      This variable is used to prevent counting of MatAssemblyBegin() that
5759    are called from within a MatAssemblyEnd().
5760 */
5761 static PetscInt MatAssemblyEnd_InUse = 0;
5762 /*@
5763   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5764   be called after completing all calls to `MatSetValues()`.
5765 
5766   Collective
5767 
5768   Input Parameters:
5769 + mat  - the matrix
5770 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5771 
5772   Level: beginner
5773 
5774   Notes:
5775   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5776   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5777 
5778   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5779   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5780   using the matrix.
5781 
5782   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5783   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
5784   a global collective operation requiring all processes that share the matrix.
5785 
5786   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5787   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5788   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5789 
5790 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5791 @*/
5792 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5793 {
5794   PetscFunctionBegin;
5795   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5796   PetscValidType(mat, 1);
5797   MatCheckPreallocated(mat, 1);
5798   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5799   if (mat->assembled) {
5800     mat->was_assembled = PETSC_TRUE;
5801     mat->assembled     = PETSC_FALSE;
5802   }
5803 
5804   if (!MatAssemblyEnd_InUse) {
5805     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5806     PetscTryTypeMethod(mat, assemblybegin, type);
5807     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5808   } else PetscTryTypeMethod(mat, assemblybegin, type);
5809   PetscFunctionReturn(PETSC_SUCCESS);
5810 }
5811 
5812 /*@
5813   MatAssembled - Indicates if a matrix has been assembled and is ready for
5814   use; for example, in matrix-vector product.
5815 
5816   Not Collective
5817 
5818   Input Parameter:
5819 . mat - the matrix
5820 
5821   Output Parameter:
5822 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5823 
5824   Level: advanced
5825 
5826 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5827 @*/
5828 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5829 {
5830   PetscFunctionBegin;
5831   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5832   PetscAssertPointer(assembled, 2);
5833   *assembled = mat->assembled;
5834   PetscFunctionReturn(PETSC_SUCCESS);
5835 }
5836 
5837 /*@
5838   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5839   be called after `MatAssemblyBegin()`.
5840 
5841   Collective
5842 
5843   Input Parameters:
5844 + mat  - the matrix
5845 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5846 
5847   Options Database Keys:
5848 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5849 . -mat_view ::ascii_info_detail      - Prints more detailed info
5850 . -mat_view                          - Prints matrix in ASCII format
5851 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5852 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5853 . -display <name>                    - Sets display name (default is host)
5854 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5855 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5856 . -viewer_socket_machine <machine>   - Machine to use for socket
5857 . -viewer_socket_port <port>         - Port number to use for socket
5858 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5859 
5860   Level: beginner
5861 
5862 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5863 @*/
5864 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5865 {
5866   static PetscInt inassm = 0;
5867   PetscBool       flg    = PETSC_FALSE;
5868 
5869   PetscFunctionBegin;
5870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5871   PetscValidType(mat, 1);
5872 
5873   inassm++;
5874   MatAssemblyEnd_InUse++;
5875   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5876     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5877     PetscTryTypeMethod(mat, assemblyend, type);
5878     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5879   } else PetscTryTypeMethod(mat, assemblyend, type);
5880 
5881   /* Flush assembly is not a true assembly */
5882   if (type != MAT_FLUSH_ASSEMBLY) {
5883     if (mat->num_ass) {
5884       if (!mat->symmetry_eternal) {
5885         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5886         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5887       }
5888       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5889       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5890     }
5891     mat->num_ass++;
5892     mat->assembled        = PETSC_TRUE;
5893     mat->ass_nonzerostate = mat->nonzerostate;
5894   }
5895 
5896   mat->insertmode = NOT_SET_VALUES;
5897   MatAssemblyEnd_InUse--;
5898   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5899   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5900     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5901 
5902     if (mat->checksymmetryonassembly) {
5903       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5904       if (flg) {
5905         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5906       } else {
5907         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5908       }
5909     }
5910     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5911   }
5912   inassm--;
5913   PetscFunctionReturn(PETSC_SUCCESS);
5914 }
5915 
5916 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5917 /*@
5918   MatSetOption - Sets a parameter option for a matrix. Some options
5919   may be specific to certain storage formats.  Some options
5920   determine how values will be inserted (or added). Sorted,
5921   row-oriented input will generally assemble the fastest. The default
5922   is row-oriented.
5923 
5924   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5925 
5926   Input Parameters:
5927 + mat - the matrix
5928 . op  - the option, one of those listed below (and possibly others),
5929 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5930 
5931   Options Describing Matrix Structure:
5932 + `MAT_SPD`                         - symmetric positive definite
5933 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5934 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5935 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5936 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5937 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5938 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5939 
5940    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5941    do not need to be computed (usually at a high cost)
5942 
5943    Options For Use with `MatSetValues()`:
5944    Insert a logically dense subblock, which can be
5945 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5946 
5947    These options reflect the data you pass in with `MatSetValues()`; it has
5948    nothing to do with how the data is stored internally in the matrix
5949    data structure.
5950 
5951    When (re)assembling a matrix, we can restrict the input for
5952    efficiency/debugging purposes.  These options include
5953 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5954 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5955 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5956 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5957 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5958 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5959         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5960         performance for very large process counts.
5961 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5962         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5963         functions, instead sending only neighbor messages.
5964 
5965   Level: intermediate
5966 
5967   Notes:
5968   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5969 
5970   Some options are relevant only for particular matrix types and
5971   are thus ignored by others.  Other options are not supported by
5972   certain matrix types and will generate an error message if set.
5973 
5974   If using Fortran to compute a matrix, one may need to
5975   use the column-oriented option (or convert to the row-oriented
5976   format).
5977 
5978   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5979   that would generate a new entry in the nonzero structure is instead
5980   ignored.  Thus, if memory has not already been allocated for this particular
5981   data, then the insertion is ignored. For dense matrices, in which
5982   the entire array is allocated, no entries are ever ignored.
5983   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5984 
5985   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5986   that would generate a new entry in the nonzero structure instead produces
5987   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
5988 
5989   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5990   that would generate a new entry that has not been preallocated will
5991   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5992   only.) This is a useful flag when debugging matrix memory preallocation.
5993   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5994 
5995   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5996   other processors should be dropped, rather than stashed.
5997   This is useful if you know that the "owning" processor is also
5998   always generating the correct matrix entries, so that PETSc need
5999   not transfer duplicate entries generated on another processor.
6000 
6001   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6002   searches during matrix assembly. When this flag is set, the hash table
6003   is created during the first matrix assembly. This hash table is
6004   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6005   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6006   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6007   supported by `MATMPIBAIJ` format only.
6008 
6009   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6010   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6011 
6012   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6013   a zero location in the matrix
6014 
6015   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6016 
6017   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6018   zero row routines and thus improves performance for very large process counts.
6019 
6020   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6021   part of the matrix (since they should match the upper triangular part).
6022 
6023   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6024   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6025   with finite difference schemes with non-periodic boundary conditions.
6026 
6027   Developer Note:
6028   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6029   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6030   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6031   not changed.
6032 
6033 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6034 @*/
6035 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6036 {
6037   PetscFunctionBegin;
6038   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6039   if (op > 0) {
6040     PetscValidLogicalCollectiveEnum(mat, op, 2);
6041     PetscValidLogicalCollectiveBool(mat, flg, 3);
6042   }
6043 
6044   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);
6045 
6046   switch (op) {
6047   case MAT_FORCE_DIAGONAL_ENTRIES:
6048     mat->force_diagonals = flg;
6049     PetscFunctionReturn(PETSC_SUCCESS);
6050   case MAT_NO_OFF_PROC_ENTRIES:
6051     mat->nooffprocentries = flg;
6052     PetscFunctionReturn(PETSC_SUCCESS);
6053   case MAT_SUBSET_OFF_PROC_ENTRIES:
6054     mat->assembly_subset = flg;
6055     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6056 #if !defined(PETSC_HAVE_MPIUNI)
6057       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6058 #endif
6059       mat->stash.first_assembly_done = PETSC_FALSE;
6060     }
6061     PetscFunctionReturn(PETSC_SUCCESS);
6062   case MAT_NO_OFF_PROC_ZERO_ROWS:
6063     mat->nooffproczerorows = flg;
6064     PetscFunctionReturn(PETSC_SUCCESS);
6065   case MAT_SPD:
6066     if (flg) {
6067       mat->spd                    = PETSC_BOOL3_TRUE;
6068       mat->symmetric              = PETSC_BOOL3_TRUE;
6069       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6070     } else {
6071       mat->spd = PETSC_BOOL3_FALSE;
6072     }
6073     break;
6074   case MAT_SYMMETRIC:
6075     mat->symmetric = PetscBoolToBool3(flg);
6076     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6077 #if !defined(PETSC_USE_COMPLEX)
6078     mat->hermitian = PetscBoolToBool3(flg);
6079 #endif
6080     break;
6081   case MAT_HERMITIAN:
6082     mat->hermitian = PetscBoolToBool3(flg);
6083     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6084 #if !defined(PETSC_USE_COMPLEX)
6085     mat->symmetric = PetscBoolToBool3(flg);
6086 #endif
6087     break;
6088   case MAT_STRUCTURALLY_SYMMETRIC:
6089     mat->structurally_symmetric = PetscBoolToBool3(flg);
6090     break;
6091   case MAT_SYMMETRY_ETERNAL:
6092     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");
6093     mat->symmetry_eternal = flg;
6094     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6095     break;
6096   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6097     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");
6098     mat->structural_symmetry_eternal = flg;
6099     break;
6100   case MAT_SPD_ETERNAL:
6101     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");
6102     mat->spd_eternal = flg;
6103     if (flg) {
6104       mat->structural_symmetry_eternal = PETSC_TRUE;
6105       mat->symmetry_eternal            = PETSC_TRUE;
6106     }
6107     break;
6108   case MAT_STRUCTURE_ONLY:
6109     mat->structure_only = flg;
6110     break;
6111   case MAT_SORTED_FULL:
6112     mat->sortedfull = flg;
6113     break;
6114   default:
6115     break;
6116   }
6117   PetscTryTypeMethod(mat, setoption, op, flg);
6118   PetscFunctionReturn(PETSC_SUCCESS);
6119 }
6120 
6121 /*@
6122   MatGetOption - Gets a parameter option that has been set for a matrix.
6123 
6124   Logically Collective
6125 
6126   Input Parameters:
6127 + mat - the matrix
6128 - op  - the option, this only responds to certain options, check the code for which ones
6129 
6130   Output Parameter:
6131 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6132 
6133   Level: intermediate
6134 
6135   Notes:
6136   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6137 
6138   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6139   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6140 
6141 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6142     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6143 @*/
6144 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6145 {
6146   PetscFunctionBegin;
6147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6148   PetscValidType(mat, 1);
6149 
6150   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);
6151   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()");
6152 
6153   switch (op) {
6154   case MAT_NO_OFF_PROC_ENTRIES:
6155     *flg = mat->nooffprocentries;
6156     break;
6157   case MAT_NO_OFF_PROC_ZERO_ROWS:
6158     *flg = mat->nooffproczerorows;
6159     break;
6160   case MAT_SYMMETRIC:
6161     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6162     break;
6163   case MAT_HERMITIAN:
6164     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6165     break;
6166   case MAT_STRUCTURALLY_SYMMETRIC:
6167     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6168     break;
6169   case MAT_SPD:
6170     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6171     break;
6172   case MAT_SYMMETRY_ETERNAL:
6173     *flg = mat->symmetry_eternal;
6174     break;
6175   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6176     *flg = mat->symmetry_eternal;
6177     break;
6178   default:
6179     break;
6180   }
6181   PetscFunctionReturn(PETSC_SUCCESS);
6182 }
6183 
6184 /*@
6185   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6186   this routine retains the old nonzero structure.
6187 
6188   Logically Collective
6189 
6190   Input Parameter:
6191 . mat - the matrix
6192 
6193   Level: intermediate
6194 
6195   Note:
6196   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.
6197   See the Performance chapter of the users manual for information on preallocating matrices.
6198 
6199 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6200 @*/
6201 PetscErrorCode MatZeroEntries(Mat mat)
6202 {
6203   PetscFunctionBegin;
6204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6205   PetscValidType(mat, 1);
6206   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6207   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");
6208   MatCheckPreallocated(mat, 1);
6209 
6210   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6211   PetscUseTypeMethod(mat, zeroentries);
6212   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6213   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6214   PetscFunctionReturn(PETSC_SUCCESS);
6215 }
6216 
6217 /*@
6218   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6219   of a set of rows and columns of a matrix.
6220 
6221   Collective
6222 
6223   Input Parameters:
6224 + mat     - the matrix
6225 . numRows - the number of rows/columns to zero
6226 . rows    - the global row indices
6227 . diag    - value put in the diagonal of the eliminated rows
6228 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6229 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6230 
6231   Level: intermediate
6232 
6233   Notes:
6234   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6235 
6236   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6237   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
6238 
6239   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6240   Krylov method to take advantage of the known solution on the zeroed rows.
6241 
6242   For the parallel case, all processes that share the matrix (i.e.,
6243   those in the communicator used for matrix creation) MUST call this
6244   routine, regardless of whether any rows being zeroed are owned by
6245   them.
6246 
6247   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6248   removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously
6249   missing.
6250 
6251   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6252   list only rows local to itself).
6253 
6254   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6255 
6256 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6257           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6258 @*/
6259 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6260 {
6261   PetscFunctionBegin;
6262   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6263   PetscValidType(mat, 1);
6264   if (numRows) PetscAssertPointer(rows, 3);
6265   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6266   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6267   MatCheckPreallocated(mat, 1);
6268 
6269   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6270   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6271   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6272   PetscFunctionReturn(PETSC_SUCCESS);
6273 }
6274 
6275 /*@
6276   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6277   of a set of rows and columns of a matrix.
6278 
6279   Collective
6280 
6281   Input Parameters:
6282 + mat  - the matrix
6283 . is   - the rows to zero
6284 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6285 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6286 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6287 
6288   Level: intermediate
6289 
6290   Note:
6291   See `MatZeroRowsColumns()` for details on how this routine operates.
6292 
6293 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6294           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6295 @*/
6296 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6297 {
6298   PetscInt        numRows;
6299   const PetscInt *rows;
6300 
6301   PetscFunctionBegin;
6302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6303   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6304   PetscValidType(mat, 1);
6305   PetscValidType(is, 2);
6306   PetscCall(ISGetLocalSize(is, &numRows));
6307   PetscCall(ISGetIndices(is, &rows));
6308   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6309   PetscCall(ISRestoreIndices(is, &rows));
6310   PetscFunctionReturn(PETSC_SUCCESS);
6311 }
6312 
6313 /*@
6314   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6315   of a set of rows of a matrix.
6316 
6317   Collective
6318 
6319   Input Parameters:
6320 + mat     - the matrix
6321 . numRows - the number of rows to zero
6322 . rows    - the global row indices
6323 . diag    - value put in the diagonal of the zeroed rows
6324 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6325 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6326 
6327   Level: intermediate
6328 
6329   Notes:
6330   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6331 
6332   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6333 
6334   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6335   Krylov method to take advantage of the known solution on the zeroed rows.
6336 
6337   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)
6338   from the matrix.
6339 
6340   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6341   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6342   formats this does not alter the nonzero structure.
6343 
6344   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6345   of the matrix is not changed the values are
6346   merely zeroed.
6347 
6348   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6349   formats can optionally remove the main diagonal entry from the
6350   nonzero structure as well, by passing 0.0 as the final argument).
6351 
6352   For the parallel case, all processes that share the matrix (i.e.,
6353   those in the communicator used for matrix creation) MUST call this
6354   routine, regardless of whether any rows being zeroed are owned by
6355   them.
6356 
6357   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6358   list only rows local to itself).
6359 
6360   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6361   owns that are to be zeroed. This saves a global synchronization in the implementation.
6362 
6363 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6364           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6365 @*/
6366 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6367 {
6368   PetscFunctionBegin;
6369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6370   PetscValidType(mat, 1);
6371   if (numRows) PetscAssertPointer(rows, 3);
6372   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6373   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6374   MatCheckPreallocated(mat, 1);
6375 
6376   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6377   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6378   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6379   PetscFunctionReturn(PETSC_SUCCESS);
6380 }
6381 
6382 /*@
6383   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6384   of a set of rows of a matrix indicated by an `IS`
6385 
6386   Collective
6387 
6388   Input Parameters:
6389 + mat  - the matrix
6390 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6391 . diag - value put in all diagonals of eliminated rows
6392 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6393 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6394 
6395   Level: intermediate
6396 
6397   Note:
6398   See `MatZeroRows()` for details on how this routine operates.
6399 
6400 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6401           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6402 @*/
6403 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6404 {
6405   PetscInt        numRows = 0;
6406   const PetscInt *rows    = NULL;
6407 
6408   PetscFunctionBegin;
6409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6410   PetscValidType(mat, 1);
6411   if (is) {
6412     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6413     PetscCall(ISGetLocalSize(is, &numRows));
6414     PetscCall(ISGetIndices(is, &rows));
6415   }
6416   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6417   if (is) PetscCall(ISRestoreIndices(is, &rows));
6418   PetscFunctionReturn(PETSC_SUCCESS);
6419 }
6420 
6421 /*@
6422   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6423   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6424 
6425   Collective
6426 
6427   Input Parameters:
6428 + mat     - the matrix
6429 . numRows - the number of rows to remove
6430 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6431 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6432 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6433 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6434 
6435   Level: intermediate
6436 
6437   Notes:
6438   See `MatZeroRows()` for details on how this routine operates.
6439 
6440   The grid coordinates are across the entire grid, not just the local portion
6441 
6442   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6443   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6444   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6445   `DM_BOUNDARY_PERIODIC` boundary type.
6446 
6447   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
6448   a single value per point) you can skip filling those indices.
6449 
6450   Fortran Note:
6451   `idxm` and `idxn` should be declared as
6452 .vb
6453     MatStencil idxm(4, m)
6454 .ve
6455   and the values inserted using
6456 .vb
6457     idxm(MatStencil_i, 1) = i
6458     idxm(MatStencil_j, 1) = j
6459     idxm(MatStencil_k, 1) = k
6460     idxm(MatStencil_c, 1) = c
6461    etc
6462 .ve
6463 
6464 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6465           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6466 @*/
6467 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6468 {
6469   PetscInt  dim    = mat->stencil.dim;
6470   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6471   PetscInt *dims   = mat->stencil.dims + 1;
6472   PetscInt *starts = mat->stencil.starts;
6473   PetscInt *dxm    = (PetscInt *)rows;
6474   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6475 
6476   PetscFunctionBegin;
6477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6478   PetscValidType(mat, 1);
6479   if (numRows) PetscAssertPointer(rows, 3);
6480 
6481   PetscCall(PetscMalloc1(numRows, &jdxm));
6482   for (i = 0; i < numRows; ++i) {
6483     /* Skip unused dimensions (they are ordered k, j, i, c) */
6484     for (j = 0; j < 3 - sdim; ++j) dxm++;
6485     /* Local index in X dir */
6486     tmp = *dxm++ - starts[0];
6487     /* Loop over remaining dimensions */
6488     for (j = 0; j < dim - 1; ++j) {
6489       /* If nonlocal, set index to be negative */
6490       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6491       /* Update local index */
6492       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6493     }
6494     /* Skip component slot if necessary */
6495     if (mat->stencil.noc) dxm++;
6496     /* Local row number */
6497     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6498   }
6499   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6500   PetscCall(PetscFree(jdxm));
6501   PetscFunctionReturn(PETSC_SUCCESS);
6502 }
6503 
6504 /*@
6505   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6506   of a set of rows and columns of a matrix.
6507 
6508   Collective
6509 
6510   Input Parameters:
6511 + mat     - the matrix
6512 . numRows - the number of rows/columns to remove
6513 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6514 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6515 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6516 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6517 
6518   Level: intermediate
6519 
6520   Notes:
6521   See `MatZeroRowsColumns()` for details on how this routine operates.
6522 
6523   The grid coordinates are across the entire grid, not just the local portion
6524 
6525   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6526   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6527   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6528   `DM_BOUNDARY_PERIODIC` boundary type.
6529 
6530   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
6531   a single value per point) you can skip filling those indices.
6532 
6533   Fortran Note:
6534   `idxm` and `idxn` should be declared as
6535 .vb
6536     MatStencil idxm(4, m)
6537 .ve
6538   and the values inserted using
6539 .vb
6540     idxm(MatStencil_i, 1) = i
6541     idxm(MatStencil_j, 1) = j
6542     idxm(MatStencil_k, 1) = k
6543     idxm(MatStencil_c, 1) = c
6544     etc
6545 .ve
6546 
6547 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6548           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6549 @*/
6550 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6551 {
6552   PetscInt  dim    = mat->stencil.dim;
6553   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6554   PetscInt *dims   = mat->stencil.dims + 1;
6555   PetscInt *starts = mat->stencil.starts;
6556   PetscInt *dxm    = (PetscInt *)rows;
6557   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6558 
6559   PetscFunctionBegin;
6560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6561   PetscValidType(mat, 1);
6562   if (numRows) PetscAssertPointer(rows, 3);
6563 
6564   PetscCall(PetscMalloc1(numRows, &jdxm));
6565   for (i = 0; i < numRows; ++i) {
6566     /* Skip unused dimensions (they are ordered k, j, i, c) */
6567     for (j = 0; j < 3 - sdim; ++j) dxm++;
6568     /* Local index in X dir */
6569     tmp = *dxm++ - starts[0];
6570     /* Loop over remaining dimensions */
6571     for (j = 0; j < dim - 1; ++j) {
6572       /* If nonlocal, set index to be negative */
6573       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6574       /* Update local index */
6575       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6576     }
6577     /* Skip component slot if necessary */
6578     if (mat->stencil.noc) dxm++;
6579     /* Local row number */
6580     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6581   }
6582   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6583   PetscCall(PetscFree(jdxm));
6584   PetscFunctionReturn(PETSC_SUCCESS);
6585 }
6586 
6587 /*@
6588   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6589   of a set of rows of a matrix; using local numbering of rows.
6590 
6591   Collective
6592 
6593   Input Parameters:
6594 + mat     - the matrix
6595 . numRows - the number of rows to remove
6596 . rows    - the local row indices
6597 . diag    - value put in all diagonals of eliminated rows
6598 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6599 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6600 
6601   Level: intermediate
6602 
6603   Notes:
6604   Before calling `MatZeroRowsLocal()`, the user must first set the
6605   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6606 
6607   See `MatZeroRows()` for details on how this routine operates.
6608 
6609 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6610           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6611 @*/
6612 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6613 {
6614   PetscFunctionBegin;
6615   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6616   PetscValidType(mat, 1);
6617   if (numRows) PetscAssertPointer(rows, 3);
6618   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6619   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6620   MatCheckPreallocated(mat, 1);
6621 
6622   if (mat->ops->zerorowslocal) {
6623     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6624   } else {
6625     IS              is, newis;
6626     const PetscInt *newRows;
6627 
6628     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6629     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6630     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6631     PetscCall(ISGetIndices(newis, &newRows));
6632     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6633     PetscCall(ISRestoreIndices(newis, &newRows));
6634     PetscCall(ISDestroy(&newis));
6635     PetscCall(ISDestroy(&is));
6636   }
6637   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6638   PetscFunctionReturn(PETSC_SUCCESS);
6639 }
6640 
6641 /*@
6642   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6643   of a set of rows of a matrix; using local numbering of rows.
6644 
6645   Collective
6646 
6647   Input Parameters:
6648 + mat  - the matrix
6649 . is   - index set of rows to remove
6650 . diag - value put in all diagonals of eliminated rows
6651 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6652 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6653 
6654   Level: intermediate
6655 
6656   Notes:
6657   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6658   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6659 
6660   See `MatZeroRows()` for details on how this routine operates.
6661 
6662 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6663           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6664 @*/
6665 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6666 {
6667   PetscInt        numRows;
6668   const PetscInt *rows;
6669 
6670   PetscFunctionBegin;
6671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6672   PetscValidType(mat, 1);
6673   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6674   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6675   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6676   MatCheckPreallocated(mat, 1);
6677 
6678   PetscCall(ISGetLocalSize(is, &numRows));
6679   PetscCall(ISGetIndices(is, &rows));
6680   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6681   PetscCall(ISRestoreIndices(is, &rows));
6682   PetscFunctionReturn(PETSC_SUCCESS);
6683 }
6684 
6685 /*@
6686   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6687   of a set of rows and columns of a matrix; using local numbering of rows.
6688 
6689   Collective
6690 
6691   Input Parameters:
6692 + mat     - the matrix
6693 . numRows - the number of rows to remove
6694 . rows    - the global row indices
6695 . diag    - value put in all diagonals of eliminated rows
6696 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6697 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6698 
6699   Level: intermediate
6700 
6701   Notes:
6702   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6703   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6704 
6705   See `MatZeroRowsColumns()` for details on how this routine operates.
6706 
6707 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6708           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6709 @*/
6710 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6711 {
6712   IS              is, newis;
6713   const PetscInt *newRows;
6714 
6715   PetscFunctionBegin;
6716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6717   PetscValidType(mat, 1);
6718   if (numRows) PetscAssertPointer(rows, 3);
6719   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6720   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6721   MatCheckPreallocated(mat, 1);
6722 
6723   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6724   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6725   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6726   PetscCall(ISGetIndices(newis, &newRows));
6727   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6728   PetscCall(ISRestoreIndices(newis, &newRows));
6729   PetscCall(ISDestroy(&newis));
6730   PetscCall(ISDestroy(&is));
6731   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6732   PetscFunctionReturn(PETSC_SUCCESS);
6733 }
6734 
6735 /*@
6736   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6737   of a set of rows and columns of a matrix; using local numbering of rows.
6738 
6739   Collective
6740 
6741   Input Parameters:
6742 + mat  - the matrix
6743 . is   - index set of rows to remove
6744 . diag - value put in all diagonals of eliminated rows
6745 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6746 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6747 
6748   Level: intermediate
6749 
6750   Notes:
6751   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6752   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6753 
6754   See `MatZeroRowsColumns()` for details on how this routine operates.
6755 
6756 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6757           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6758 @*/
6759 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6760 {
6761   PetscInt        numRows;
6762   const PetscInt *rows;
6763 
6764   PetscFunctionBegin;
6765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6766   PetscValidType(mat, 1);
6767   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6768   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6769   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6770   MatCheckPreallocated(mat, 1);
6771 
6772   PetscCall(ISGetLocalSize(is, &numRows));
6773   PetscCall(ISGetIndices(is, &rows));
6774   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6775   PetscCall(ISRestoreIndices(is, &rows));
6776   PetscFunctionReturn(PETSC_SUCCESS);
6777 }
6778 
6779 /*@
6780   MatGetSize - Returns the numbers of rows and columns in a matrix.
6781 
6782   Not Collective
6783 
6784   Input Parameter:
6785 . mat - the matrix
6786 
6787   Output Parameters:
6788 + m - the number of global rows
6789 - n - the number of global columns
6790 
6791   Level: beginner
6792 
6793   Note:
6794   Both output parameters can be `NULL` on input.
6795 
6796 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6797 @*/
6798 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6799 {
6800   PetscFunctionBegin;
6801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6802   if (m) *m = mat->rmap->N;
6803   if (n) *n = mat->cmap->N;
6804   PetscFunctionReturn(PETSC_SUCCESS);
6805 }
6806 
6807 /*@
6808   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6809   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6810 
6811   Not Collective
6812 
6813   Input Parameter:
6814 . mat - the matrix
6815 
6816   Output Parameters:
6817 + m - the number of local rows, use `NULL` to not obtain this value
6818 - n - the number of local columns, use `NULL` to not obtain this value
6819 
6820   Level: beginner
6821 
6822 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6823 @*/
6824 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6825 {
6826   PetscFunctionBegin;
6827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6828   if (m) PetscAssertPointer(m, 2);
6829   if (n) PetscAssertPointer(n, 3);
6830   if (m) *m = mat->rmap->n;
6831   if (n) *n = mat->cmap->n;
6832   PetscFunctionReturn(PETSC_SUCCESS);
6833 }
6834 
6835 /*@
6836   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6837   vector one multiplies this matrix by that are owned by this processor.
6838 
6839   Not Collective, unless matrix has not been allocated, then collective
6840 
6841   Input Parameter:
6842 . mat - the matrix
6843 
6844   Output Parameters:
6845 + m - the global index of the first local column, use `NULL` to not obtain this value
6846 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6847 
6848   Level: developer
6849 
6850   Notes:
6851   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6852 
6853   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6854   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6855 
6856   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6857   the local values in the matrix.
6858 
6859   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6860   Layouts](sec_matlayout) for details on matrix layouts.
6861 
6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6863           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6864 @*/
6865 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6866 {
6867   PetscFunctionBegin;
6868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6869   PetscValidType(mat, 1);
6870   if (m) PetscAssertPointer(m, 2);
6871   if (n) PetscAssertPointer(n, 3);
6872   MatCheckPreallocated(mat, 1);
6873   if (m) *m = mat->cmap->rstart;
6874   if (n) *n = mat->cmap->rend;
6875   PetscFunctionReturn(PETSC_SUCCESS);
6876 }
6877 
6878 /*@
6879   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6880   this MPI process.
6881 
6882   Not Collective
6883 
6884   Input Parameter:
6885 . mat - the matrix
6886 
6887   Output Parameters:
6888 + m - the global index of the first local row, use `NULL` to not obtain this value
6889 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6890 
6891   Level: beginner
6892 
6893   Notes:
6894   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6895 
6896   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6897   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6898 
6899   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6900   the local values in the matrix.
6901 
6902   The high argument is one more than the last element stored locally.
6903 
6904   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6905   would contain the result of a matrix vector product with this matrix. See [Matrix
6906   Layouts](sec_matlayout) for details on matrix layouts.
6907 
6908 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6909           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6910 @*/
6911 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6912 {
6913   PetscFunctionBegin;
6914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6915   PetscValidType(mat, 1);
6916   if (m) PetscAssertPointer(m, 2);
6917   if (n) PetscAssertPointer(n, 3);
6918   MatCheckPreallocated(mat, 1);
6919   if (m) *m = mat->rmap->rstart;
6920   if (n) *n = mat->rmap->rend;
6921   PetscFunctionReturn(PETSC_SUCCESS);
6922 }
6923 
6924 /*@C
6925   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6926   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6927 
6928   Not Collective, unless matrix has not been allocated
6929 
6930   Input Parameter:
6931 . mat - the matrix
6932 
6933   Output Parameter:
6934 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6935            where `size` is the number of MPI processes used by `mat`
6936 
6937   Level: beginner
6938 
6939   Notes:
6940   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6941 
6942   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6943   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6944 
6945   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6946   the local values in the matrix.
6947 
6948   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6949   would contain the result of a matrix vector product with this matrix. See [Matrix
6950   Layouts](sec_matlayout) for details on matrix layouts.
6951 
6952 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6953           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6954           `DMDAGetGhostCorners()`, `DM`
6955 @*/
6956 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6957 {
6958   PetscFunctionBegin;
6959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6960   PetscValidType(mat, 1);
6961   MatCheckPreallocated(mat, 1);
6962   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6963   PetscFunctionReturn(PETSC_SUCCESS);
6964 }
6965 
6966 /*@C
6967   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6968   vector one multiplies this vector by that are owned by each processor.
6969 
6970   Not Collective, unless matrix has not been allocated
6971 
6972   Input Parameter:
6973 . mat - the matrix
6974 
6975   Output Parameter:
6976 . ranges - start of each processors portion plus one more than the total length at the end
6977 
6978   Level: beginner
6979 
6980   Notes:
6981   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6982 
6983   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6984   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6985 
6986   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6987   the local values in the matrix.
6988 
6989   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6990   Layouts](sec_matlayout) for details on matrix layouts.
6991 
6992 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6993           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6994           `DMDAGetGhostCorners()`, `DM`
6995 @*/
6996 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6997 {
6998   PetscFunctionBegin;
6999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7000   PetscValidType(mat, 1);
7001   MatCheckPreallocated(mat, 1);
7002   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7003   PetscFunctionReturn(PETSC_SUCCESS);
7004 }
7005 
7006 /*@
7007   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7008 
7009   Not Collective
7010 
7011   Input Parameter:
7012 . A - matrix
7013 
7014   Output Parameters:
7015 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7016 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7017 
7018   Level: intermediate
7019 
7020   Note:
7021   You should call `ISDestroy()` on the returned `IS`
7022 
7023   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7024   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7025   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7026   details on matrix layouts.
7027 
7028 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7029 @*/
7030 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7031 {
7032   PetscErrorCode (*f)(Mat, IS *, IS *);
7033 
7034   PetscFunctionBegin;
7035   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7036   PetscValidType(A, 1);
7037   MatCheckPreallocated(A, 1);
7038   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7039   if (f) {
7040     PetscCall((*f)(A, rows, cols));
7041   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7042     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7043     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7044   }
7045   PetscFunctionReturn(PETSC_SUCCESS);
7046 }
7047 
7048 /*@
7049   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7050   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7051   to complete the factorization.
7052 
7053   Collective
7054 
7055   Input Parameters:
7056 + fact - the factorized matrix obtained with `MatGetFactor()`
7057 . mat  - the matrix
7058 . row  - row permutation
7059 . col  - column permutation
7060 - info - structure containing
7061 .vb
7062       levels - number of levels of fill.
7063       expected fill - as ratio of original fill.
7064       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7065                 missing diagonal entries)
7066 .ve
7067 
7068   Level: developer
7069 
7070   Notes:
7071   See [Matrix Factorization](sec_matfactor) for additional information.
7072 
7073   Most users should employ the `KSP` interface for linear solvers
7074   instead of working directly with matrix algebra routines such as this.
7075   See, e.g., `KSPCreate()`.
7076 
7077   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7078 
7079   Fortran Note:
7080   A valid (non-null) `info` argument must be provided
7081 
7082 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7083           `MatGetOrdering()`, `MatFactorInfo`
7084 @*/
7085 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7086 {
7087   PetscFunctionBegin;
7088   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7089   PetscValidType(mat, 2);
7090   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7091   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7092   PetscAssertPointer(info, 5);
7093   PetscAssertPointer(fact, 1);
7094   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7095   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7096   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7097   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7098   MatCheckPreallocated(mat, 2);
7099 
7100   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7101   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7102   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7103   PetscFunctionReturn(PETSC_SUCCESS);
7104 }
7105 
7106 /*@
7107   MatICCFactorSymbolic - Performs symbolic incomplete
7108   Cholesky factorization for a symmetric matrix.  Use
7109   `MatCholeskyFactorNumeric()` to complete the factorization.
7110 
7111   Collective
7112 
7113   Input Parameters:
7114 + fact - the factorized matrix obtained with `MatGetFactor()`
7115 . mat  - the matrix to be factored
7116 . perm - row and column permutation
7117 - info - structure containing
7118 .vb
7119       levels - number of levels of fill.
7120       expected fill - as ratio of original fill.
7121 .ve
7122 
7123   Level: developer
7124 
7125   Notes:
7126   Most users should employ the `KSP` interface for linear solvers
7127   instead of working directly with matrix algebra routines such as this.
7128   See, e.g., `KSPCreate()`.
7129 
7130   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7131 
7132   Fortran Note:
7133   A valid (non-null) `info` argument must be provided
7134 
7135 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7136 @*/
7137 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7138 {
7139   PetscFunctionBegin;
7140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7141   PetscValidType(mat, 2);
7142   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7143   PetscAssertPointer(info, 4);
7144   PetscAssertPointer(fact, 1);
7145   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7146   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7147   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7148   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7149   MatCheckPreallocated(mat, 2);
7150 
7151   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7152   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7153   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7154   PetscFunctionReturn(PETSC_SUCCESS);
7155 }
7156 
7157 /*@C
7158   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7159   points to an array of valid matrices, they may be reused to store the new
7160   submatrices.
7161 
7162   Collective
7163 
7164   Input Parameters:
7165 + mat   - the matrix
7166 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7167 . irow  - index set of rows to extract
7168 . icol  - index set of columns to extract
7169 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7170 
7171   Output Parameter:
7172 . submat - the array of submatrices
7173 
7174   Level: advanced
7175 
7176   Notes:
7177   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7178   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7179   to extract a parallel submatrix.
7180 
7181   Some matrix types place restrictions on the row and column
7182   indices, such as that they be sorted or that they be equal to each other.
7183 
7184   The index sets may not have duplicate entries.
7185 
7186   When extracting submatrices from a parallel matrix, each processor can
7187   form a different submatrix by setting the rows and columns of its
7188   individual index sets according to the local submatrix desired.
7189 
7190   When finished using the submatrices, the user should destroy
7191   them with `MatDestroySubMatrices()`.
7192 
7193   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7194   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7195 
7196   This routine creates the matrices in submat; you should NOT create them before
7197   calling it. It also allocates the array of matrix pointers submat.
7198 
7199   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7200   request one row/column in a block, they must request all rows/columns that are in
7201   that block. For example, if the block size is 2 you cannot request just row 0 and
7202   column 0.
7203 
7204   Fortran Note:
7205 .vb
7206   Mat, pointer :: submat(:)
7207 .ve
7208 
7209 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7210 @*/
7211 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7212 {
7213   PetscInt  i;
7214   PetscBool eq;
7215 
7216   PetscFunctionBegin;
7217   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7218   PetscValidType(mat, 1);
7219   if (n) {
7220     PetscAssertPointer(irow, 3);
7221     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7222     PetscAssertPointer(icol, 4);
7223     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7224   }
7225   PetscAssertPointer(submat, 6);
7226   if (n && scall == MAT_REUSE_MATRIX) {
7227     PetscAssertPointer(*submat, 6);
7228     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7229   }
7230   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7231   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7232   MatCheckPreallocated(mat, 1);
7233   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7234   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7235   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7236   for (i = 0; i < n; i++) {
7237     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7238     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7239     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7240 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7241     if (mat->boundtocpu && mat->bindingpropagates) {
7242       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7243       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7244     }
7245 #endif
7246   }
7247   PetscFunctionReturn(PETSC_SUCCESS);
7248 }
7249 
7250 /*@C
7251   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7252 
7253   Collective
7254 
7255   Input Parameters:
7256 + mat   - the matrix
7257 . n     - the number of submatrixes to be extracted
7258 . irow  - index set of rows to extract
7259 . icol  - index set of columns to extract
7260 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7261 
7262   Output Parameter:
7263 . submat - the array of submatrices
7264 
7265   Level: advanced
7266 
7267   Note:
7268   This is used by `PCGASM`
7269 
7270 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7271 @*/
7272 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7273 {
7274   PetscInt  i;
7275   PetscBool eq;
7276 
7277   PetscFunctionBegin;
7278   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7279   PetscValidType(mat, 1);
7280   if (n) {
7281     PetscAssertPointer(irow, 3);
7282     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7283     PetscAssertPointer(icol, 4);
7284     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7285   }
7286   PetscAssertPointer(submat, 6);
7287   if (n && scall == MAT_REUSE_MATRIX) {
7288     PetscAssertPointer(*submat, 6);
7289     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7290   }
7291   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7292   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7293   MatCheckPreallocated(mat, 1);
7294 
7295   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7296   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7297   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7298   for (i = 0; i < n; i++) {
7299     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7300     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7301   }
7302   PetscFunctionReturn(PETSC_SUCCESS);
7303 }
7304 
7305 /*@C
7306   MatDestroyMatrices - Destroys an array of matrices
7307 
7308   Collective
7309 
7310   Input Parameters:
7311 + n   - the number of local matrices
7312 - mat - the matrices (this is a pointer to the array of matrices)
7313 
7314   Level: advanced
7315 
7316   Notes:
7317   Frees not only the matrices, but also the array that contains the matrices
7318 
7319   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7320 
7321 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7322 @*/
7323 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7324 {
7325   PetscInt i;
7326 
7327   PetscFunctionBegin;
7328   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7329   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7330   PetscAssertPointer(mat, 2);
7331 
7332   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7333 
7334   /* memory is allocated even if n = 0 */
7335   PetscCall(PetscFree(*mat));
7336   PetscFunctionReturn(PETSC_SUCCESS);
7337 }
7338 
7339 /*@C
7340   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7341 
7342   Collective
7343 
7344   Input Parameters:
7345 + n   - the number of local matrices
7346 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7347 
7348   Level: advanced
7349 
7350   Note:
7351   Frees not only the matrices, but also the array that contains the matrices
7352 
7353 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7354 @*/
7355 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7356 {
7357   Mat mat0;
7358 
7359   PetscFunctionBegin;
7360   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7361   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7362   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7363   PetscAssertPointer(mat, 2);
7364 
7365   mat0 = (*mat)[0];
7366   if (mat0 && mat0->ops->destroysubmatrices) {
7367     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7368   } else {
7369     PetscCall(MatDestroyMatrices(n, mat));
7370   }
7371   PetscFunctionReturn(PETSC_SUCCESS);
7372 }
7373 
7374 /*@
7375   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7376 
7377   Collective
7378 
7379   Input Parameter:
7380 . mat - the matrix
7381 
7382   Output Parameter:
7383 . matstruct - the sequential matrix with the nonzero structure of `mat`
7384 
7385   Level: developer
7386 
7387 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7388 @*/
7389 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7390 {
7391   PetscFunctionBegin;
7392   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7393   PetscAssertPointer(matstruct, 2);
7394 
7395   PetscValidType(mat, 1);
7396   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7397   MatCheckPreallocated(mat, 1);
7398 
7399   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7400   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7401   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7402   PetscFunctionReturn(PETSC_SUCCESS);
7403 }
7404 
7405 /*@C
7406   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7407 
7408   Collective
7409 
7410   Input Parameter:
7411 . mat - the matrix
7412 
7413   Level: advanced
7414 
7415   Note:
7416   This is not needed, one can just call `MatDestroy()`
7417 
7418 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7419 @*/
7420 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7421 {
7422   PetscFunctionBegin;
7423   PetscAssertPointer(mat, 1);
7424   PetscCall(MatDestroy(mat));
7425   PetscFunctionReturn(PETSC_SUCCESS);
7426 }
7427 
7428 /*@
7429   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7430   replaces the index sets by larger ones that represent submatrices with
7431   additional overlap.
7432 
7433   Collective
7434 
7435   Input Parameters:
7436 + mat - the matrix
7437 . n   - the number of index sets
7438 . is  - the array of index sets (these index sets will changed during the call)
7439 - ov  - the additional overlap requested
7440 
7441   Options Database Key:
7442 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7443 
7444   Level: developer
7445 
7446   Note:
7447   The computed overlap preserves the matrix block sizes when the blocks are square.
7448   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7449   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7450 
7451 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7452 @*/
7453 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7454 {
7455   PetscInt i, bs, cbs;
7456 
7457   PetscFunctionBegin;
7458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7459   PetscValidType(mat, 1);
7460   PetscValidLogicalCollectiveInt(mat, n, 2);
7461   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7462   if (n) {
7463     PetscAssertPointer(is, 3);
7464     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7465   }
7466   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7467   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7468   MatCheckPreallocated(mat, 1);
7469 
7470   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7471   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7472   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7473   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7474   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7475   if (bs == cbs) {
7476     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7477   }
7478   PetscFunctionReturn(PETSC_SUCCESS);
7479 }
7480 
7481 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7482 
7483 /*@
7484   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7485   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7486   additional overlap.
7487 
7488   Collective
7489 
7490   Input Parameters:
7491 + mat - the matrix
7492 . n   - the number of index sets
7493 . is  - the array of index sets (these index sets will changed during the call)
7494 - ov  - the additional overlap requested
7495 
7496   `   Options Database Key:
7497 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7498 
7499   Level: developer
7500 
7501 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7502 @*/
7503 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7504 {
7505   PetscInt i;
7506 
7507   PetscFunctionBegin;
7508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7509   PetscValidType(mat, 1);
7510   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7511   if (n) {
7512     PetscAssertPointer(is, 3);
7513     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7514   }
7515   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7516   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7517   MatCheckPreallocated(mat, 1);
7518   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7519   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7520   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7521   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7522   PetscFunctionReturn(PETSC_SUCCESS);
7523 }
7524 
7525 /*@
7526   MatGetBlockSize - Returns the matrix block size.
7527 
7528   Not Collective
7529 
7530   Input Parameter:
7531 . mat - the matrix
7532 
7533   Output Parameter:
7534 . bs - block size
7535 
7536   Level: intermediate
7537 
7538   Notes:
7539   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7540 
7541   If the block size has not been set yet this routine returns 1.
7542 
7543 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7544 @*/
7545 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7546 {
7547   PetscFunctionBegin;
7548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7549   PetscAssertPointer(bs, 2);
7550   *bs = mat->rmap->bs;
7551   PetscFunctionReturn(PETSC_SUCCESS);
7552 }
7553 
7554 /*@
7555   MatGetBlockSizes - Returns the matrix block row and column sizes.
7556 
7557   Not Collective
7558 
7559   Input Parameter:
7560 . mat - the matrix
7561 
7562   Output Parameters:
7563 + rbs - row block size
7564 - cbs - column block size
7565 
7566   Level: intermediate
7567 
7568   Notes:
7569   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7570   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7571 
7572   If a block size has not been set yet this routine returns 1.
7573 
7574 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7575 @*/
7576 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7577 {
7578   PetscFunctionBegin;
7579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7580   if (rbs) PetscAssertPointer(rbs, 2);
7581   if (cbs) PetscAssertPointer(cbs, 3);
7582   if (rbs) *rbs = mat->rmap->bs;
7583   if (cbs) *cbs = mat->cmap->bs;
7584   PetscFunctionReturn(PETSC_SUCCESS);
7585 }
7586 
7587 /*@
7588   MatSetBlockSize - Sets the matrix block size.
7589 
7590   Logically Collective
7591 
7592   Input Parameters:
7593 + mat - the matrix
7594 - bs  - block size
7595 
7596   Level: intermediate
7597 
7598   Notes:
7599   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7600   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7601 
7602   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7603   is compatible with the matrix local sizes.
7604 
7605 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7606 @*/
7607 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7608 {
7609   PetscFunctionBegin;
7610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7611   PetscValidLogicalCollectiveInt(mat, bs, 2);
7612   PetscCall(MatSetBlockSizes(mat, bs, bs));
7613   PetscFunctionReturn(PETSC_SUCCESS);
7614 }
7615 
7616 typedef struct {
7617   PetscInt         n;
7618   IS              *is;
7619   Mat             *mat;
7620   PetscObjectState nonzerostate;
7621   Mat              C;
7622 } EnvelopeData;
7623 
7624 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7625 {
7626   EnvelopeData *edata = (EnvelopeData *)*ptr;
7627 
7628   PetscFunctionBegin;
7629   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7630   PetscCall(PetscFree(edata->is));
7631   PetscCall(PetscFree(edata));
7632   PetscFunctionReturn(PETSC_SUCCESS);
7633 }
7634 
7635 /*@
7636   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7637   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7638 
7639   Collective
7640 
7641   Input Parameter:
7642 . mat - the matrix
7643 
7644   Level: intermediate
7645 
7646   Notes:
7647   There can be zeros within the blocks
7648 
7649   The blocks can overlap between processes, including laying on more than two processes
7650 
7651 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7652 @*/
7653 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7654 {
7655   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7656   PetscInt          *diag, *odiag, sc;
7657   VecScatter         scatter;
7658   PetscScalar       *seqv;
7659   const PetscScalar *parv;
7660   const PetscInt    *ia, *ja;
7661   PetscBool          set, flag, done;
7662   Mat                AA = mat, A;
7663   MPI_Comm           comm;
7664   PetscMPIInt        rank, size, tag;
7665   MPI_Status         status;
7666   PetscContainer     container;
7667   EnvelopeData      *edata;
7668   Vec                seq, par;
7669   IS                 isglobal;
7670 
7671   PetscFunctionBegin;
7672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7673   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7674   if (!set || !flag) {
7675     /* TODO: only needs nonzero structure of transpose */
7676     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7677     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7678   }
7679   PetscCall(MatAIJGetLocalMat(AA, &A));
7680   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7681   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7682 
7683   PetscCall(MatGetLocalSize(mat, &n, NULL));
7684   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7685   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7686   PetscCallMPI(MPI_Comm_size(comm, &size));
7687   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7688 
7689   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7690 
7691   if (rank > 0) {
7692     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7693     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7694   }
7695   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7696   for (i = 0; i < n; i++) {
7697     env = PetscMax(env, ja[ia[i + 1] - 1]);
7698     II  = rstart + i;
7699     if (env == II) {
7700       starts[lblocks]  = tbs;
7701       sizes[lblocks++] = 1 + II - tbs;
7702       tbs              = 1 + II;
7703     }
7704   }
7705   if (rank < size - 1) {
7706     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7707     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7708   }
7709 
7710   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7711   if (!set || !flag) PetscCall(MatDestroy(&AA));
7712   PetscCall(MatDestroy(&A));
7713 
7714   PetscCall(PetscNew(&edata));
7715   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7716   edata->n = lblocks;
7717   /* create IS needed for extracting blocks from the original matrix */
7718   PetscCall(PetscMalloc1(lblocks, &edata->is));
7719   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7720 
7721   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7722   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7723   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7724   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7725   PetscCall(MatSetType(edata->C, MATAIJ));
7726 
7727   /* Communicate the start and end of each row, from each block to the correct rank */
7728   /* TODO: Use PetscSF instead of VecScatter */
7729   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7730   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7731   PetscCall(VecGetArrayWrite(seq, &seqv));
7732   for (PetscInt i = 0; i < lblocks; i++) {
7733     for (PetscInt j = 0; j < sizes[i]; j++) {
7734       seqv[cnt]     = starts[i];
7735       seqv[cnt + 1] = starts[i] + sizes[i];
7736       cnt += 2;
7737     }
7738   }
7739   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7740   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7741   sc -= cnt;
7742   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7743   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7744   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7745   PetscCall(ISDestroy(&isglobal));
7746   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7747   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7748   PetscCall(VecScatterDestroy(&scatter));
7749   PetscCall(VecDestroy(&seq));
7750   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7751   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7752   PetscCall(VecGetArrayRead(par, &parv));
7753   cnt = 0;
7754   PetscCall(MatGetSize(mat, NULL, &n));
7755   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7756     PetscInt start, end, d = 0, od = 0;
7757 
7758     start = (PetscInt)PetscRealPart(parv[cnt]);
7759     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7760     cnt += 2;
7761 
7762     if (start < cstart) {
7763       od += cstart - start + n - cend;
7764       d += cend - cstart;
7765     } else if (start < cend) {
7766       od += n - cend;
7767       d += cend - start;
7768     } else od += n - start;
7769     if (end <= cstart) {
7770       od -= cstart - end + n - cend;
7771       d -= cend - cstart;
7772     } else if (end < cend) {
7773       od -= n - cend;
7774       d -= cend - end;
7775     } else od -= n - end;
7776 
7777     odiag[i] = od;
7778     diag[i]  = d;
7779   }
7780   PetscCall(VecRestoreArrayRead(par, &parv));
7781   PetscCall(VecDestroy(&par));
7782   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7783   PetscCall(PetscFree2(diag, odiag));
7784   PetscCall(PetscFree2(sizes, starts));
7785 
7786   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7787   PetscCall(PetscContainerSetPointer(container, edata));
7788   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7789   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7790   PetscCall(PetscObjectDereference((PetscObject)container));
7791   PetscFunctionReturn(PETSC_SUCCESS);
7792 }
7793 
7794 /*@
7795   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7796 
7797   Collective
7798 
7799   Input Parameters:
7800 + A     - the matrix
7801 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7802 
7803   Output Parameter:
7804 . C - matrix with inverted block diagonal of `A`
7805 
7806   Level: advanced
7807 
7808   Note:
7809   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7810 
7811 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7812 @*/
7813 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7814 {
7815   PetscContainer   container;
7816   EnvelopeData    *edata;
7817   PetscObjectState nonzerostate;
7818 
7819   PetscFunctionBegin;
7820   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7821   if (!container) {
7822     PetscCall(MatComputeVariableBlockEnvelope(A));
7823     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7824   }
7825   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7826   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7827   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7828   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7829 
7830   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7831   *C = edata->C;
7832 
7833   for (PetscInt i = 0; i < edata->n; i++) {
7834     Mat          D;
7835     PetscScalar *dvalues;
7836 
7837     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7838     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7839     PetscCall(MatSeqDenseInvert(D));
7840     PetscCall(MatDenseGetArray(D, &dvalues));
7841     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7842     PetscCall(MatDestroy(&D));
7843   }
7844   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7845   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7846   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7847   PetscFunctionReturn(PETSC_SUCCESS);
7848 }
7849 
7850 /*@
7851   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7852 
7853   Not Collective
7854 
7855   Input Parameters:
7856 + mat     - the matrix
7857 . nblocks - the number of blocks on this process, each block can only exist on a single process
7858 - bsizes  - the block sizes
7859 
7860   Level: intermediate
7861 
7862   Notes:
7863   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7864 
7865   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.
7866 
7867 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7868           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7869 @*/
7870 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7871 {
7872   PetscInt ncnt = 0, nlocal;
7873 
7874   PetscFunctionBegin;
7875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7876   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7877   PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal);
7878   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7879   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);
7880   PetscCall(PetscFree(mat->bsizes));
7881   mat->nblocks = nblocks;
7882   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7883   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7884   PetscFunctionReturn(PETSC_SUCCESS);
7885 }
7886 
7887 /*@C
7888   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7889 
7890   Not Collective; No Fortran Support
7891 
7892   Input Parameter:
7893 . mat - the matrix
7894 
7895   Output Parameters:
7896 + nblocks - the number of blocks on this process
7897 - bsizes  - the block sizes
7898 
7899   Level: intermediate
7900 
7901 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7902 @*/
7903 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7904 {
7905   PetscFunctionBegin;
7906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7907   if (nblocks) *nblocks = mat->nblocks;
7908   if (bsizes) *bsizes = mat->bsizes;
7909   PetscFunctionReturn(PETSC_SUCCESS);
7910 }
7911 
7912 /*@
7913   MatSetBlockSizes - Sets the matrix block row and column sizes.
7914 
7915   Logically Collective
7916 
7917   Input Parameters:
7918 + mat - the matrix
7919 . rbs - row block size
7920 - cbs - column block size
7921 
7922   Level: intermediate
7923 
7924   Notes:
7925   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7926   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7927   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7928 
7929   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7930   are compatible with the matrix local sizes.
7931 
7932   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7933 
7934 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7935 @*/
7936 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7937 {
7938   PetscFunctionBegin;
7939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7940   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7941   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7942   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7943   if (mat->rmap->refcnt) {
7944     ISLocalToGlobalMapping l2g  = NULL;
7945     PetscLayout            nmap = NULL;
7946 
7947     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7948     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7949     PetscCall(PetscLayoutDestroy(&mat->rmap));
7950     mat->rmap          = nmap;
7951     mat->rmap->mapping = l2g;
7952   }
7953   if (mat->cmap->refcnt) {
7954     ISLocalToGlobalMapping l2g  = NULL;
7955     PetscLayout            nmap = NULL;
7956 
7957     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7958     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7959     PetscCall(PetscLayoutDestroy(&mat->cmap));
7960     mat->cmap          = nmap;
7961     mat->cmap->mapping = l2g;
7962   }
7963   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7964   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7965   PetscFunctionReturn(PETSC_SUCCESS);
7966 }
7967 
7968 /*@
7969   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7970 
7971   Logically Collective
7972 
7973   Input Parameters:
7974 + mat     - the matrix
7975 . fromRow - matrix from which to copy row block size
7976 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7977 
7978   Level: developer
7979 
7980 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7981 @*/
7982 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7983 {
7984   PetscFunctionBegin;
7985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7986   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7987   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7988   PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7989   PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7990   PetscFunctionReturn(PETSC_SUCCESS);
7991 }
7992 
7993 /*@
7994   MatResidual - Default routine to calculate the residual r = b - Ax
7995 
7996   Collective
7997 
7998   Input Parameters:
7999 + mat - the matrix
8000 . b   - the right-hand-side
8001 - x   - the approximate solution
8002 
8003   Output Parameter:
8004 . r - location to store the residual
8005 
8006   Level: developer
8007 
8008 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8009 @*/
8010 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8011 {
8012   PetscFunctionBegin;
8013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8014   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8015   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8016   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8017   PetscValidType(mat, 1);
8018   MatCheckPreallocated(mat, 1);
8019   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8020   if (!mat->ops->residual) {
8021     PetscCall(MatMult(mat, x, r));
8022     PetscCall(VecAYPX(r, -1.0, b));
8023   } else {
8024     PetscUseTypeMethod(mat, residual, b, x, r);
8025   }
8026   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8027   PetscFunctionReturn(PETSC_SUCCESS);
8028 }
8029 
8030 /*@C
8031   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8032 
8033   Collective
8034 
8035   Input Parameters:
8036 + mat             - the matrix
8037 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8038 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8039 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8040                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8041                  always used.
8042 
8043   Output Parameters:
8044 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8045 . 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
8046 . ja   - the column indices, use `NULL` if not needed
8047 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8048            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8049 
8050   Level: developer
8051 
8052   Notes:
8053   You CANNOT change any of the ia[] or ja[] values.
8054 
8055   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8056 
8057   Fortran Notes:
8058   Use
8059 .vb
8060     PetscInt, pointer :: ia(:),ja(:)
8061     call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8062     ! Access the ith and jth entries via ia(i) and ja(j)
8063 .ve
8064 
8065 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8066 @*/
8067 PetscErrorCode MatGetRowIJ(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 (n) PetscAssertPointer(n, 5);
8073   if (ia) PetscAssertPointer(ia, 6);
8074   if (ja) PetscAssertPointer(ja, 7);
8075   if (done) PetscAssertPointer(done, 8);
8076   MatCheckPreallocated(mat, 1);
8077   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8078   else {
8079     if (done) *done = PETSC_TRUE;
8080     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8081     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8082     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8083   }
8084   PetscFunctionReturn(PETSC_SUCCESS);
8085 }
8086 
8087 /*@C
8088   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8089 
8090   Collective
8091 
8092   Input Parameters:
8093 + mat             - the matrix
8094 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8095 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8096                 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 . n               - number of columns in the (possibly compressed) matrix
8101 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8102 - ja              - the row indices
8103 
8104   Output Parameter:
8105 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8106 
8107   Level: developer
8108 
8109 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8110 @*/
8111 PetscErrorCode MatGetColumnIJ(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   PetscAssertPointer(n, 5);
8117   if (ia) PetscAssertPointer(ia, 6);
8118   if (ja) PetscAssertPointer(ja, 7);
8119   PetscAssertPointer(done, 8);
8120   MatCheckPreallocated(mat, 1);
8121   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8122   else {
8123     *done = PETSC_TRUE;
8124     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8125   }
8126   PetscFunctionReturn(PETSC_SUCCESS);
8127 }
8128 
8129 /*@C
8130   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8131 
8132   Collective
8133 
8134   Input Parameters:
8135 + mat             - the matrix
8136 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8137 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8138 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8139                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8140                     always used.
8141 . n               - size of (possibly compressed) matrix
8142 . ia              - the row pointers
8143 - ja              - the column indices
8144 
8145   Output Parameter:
8146 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8147 
8148   Level: developer
8149 
8150   Note:
8151   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8152   us of the array after it has been restored. If you pass `NULL`, it will
8153   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8154 
8155 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8156 @*/
8157 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8158 {
8159   PetscFunctionBegin;
8160   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8161   PetscValidType(mat, 1);
8162   if (ia) PetscAssertPointer(ia, 6);
8163   if (ja) PetscAssertPointer(ja, 7);
8164   if (done) PetscAssertPointer(done, 8);
8165   MatCheckPreallocated(mat, 1);
8166 
8167   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8168   else {
8169     if (done) *done = PETSC_TRUE;
8170     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8171     if (n) *n = 0;
8172     if (ia) *ia = NULL;
8173     if (ja) *ja = NULL;
8174   }
8175   PetscFunctionReturn(PETSC_SUCCESS);
8176 }
8177 
8178 /*@C
8179   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8180 
8181   Collective
8182 
8183   Input Parameters:
8184 + mat             - the matrix
8185 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8186 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8187 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8188                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8189                     always used.
8190 
8191   Output Parameters:
8192 + n    - size of (possibly compressed) matrix
8193 . ia   - the column pointers
8194 . ja   - the row indices
8195 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8196 
8197   Level: developer
8198 
8199 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8200 @*/
8201 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8202 {
8203   PetscFunctionBegin;
8204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8205   PetscValidType(mat, 1);
8206   if (ia) PetscAssertPointer(ia, 6);
8207   if (ja) PetscAssertPointer(ja, 7);
8208   PetscAssertPointer(done, 8);
8209   MatCheckPreallocated(mat, 1);
8210 
8211   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8212   else {
8213     *done = PETSC_TRUE;
8214     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8215     if (n) *n = 0;
8216     if (ia) *ia = NULL;
8217     if (ja) *ja = NULL;
8218   }
8219   PetscFunctionReturn(PETSC_SUCCESS);
8220 }
8221 
8222 /*@
8223   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8224   `MatGetColumnIJ()`.
8225 
8226   Collective
8227 
8228   Input Parameters:
8229 + mat        - the matrix
8230 . ncolors    - maximum color value
8231 . n          - number of entries in colorarray
8232 - colorarray - array indicating color for each column
8233 
8234   Output Parameter:
8235 . iscoloring - coloring generated using colorarray information
8236 
8237   Level: developer
8238 
8239 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8240 @*/
8241 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8242 {
8243   PetscFunctionBegin;
8244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8245   PetscValidType(mat, 1);
8246   PetscAssertPointer(colorarray, 4);
8247   PetscAssertPointer(iscoloring, 5);
8248   MatCheckPreallocated(mat, 1);
8249 
8250   if (!mat->ops->coloringpatch) {
8251     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8252   } else {
8253     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8254   }
8255   PetscFunctionReturn(PETSC_SUCCESS);
8256 }
8257 
8258 /*@
8259   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8260 
8261   Logically Collective
8262 
8263   Input Parameter:
8264 . mat - the factored matrix to be reset
8265 
8266   Level: developer
8267 
8268   Notes:
8269   This routine should be used only with factored matrices formed by in-place
8270   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8271   format).  This option can save memory, for example, when solving nonlinear
8272   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8273   ILU(0) preconditioner.
8274 
8275   One can specify in-place ILU(0) factorization by calling
8276 .vb
8277      PCType(pc,PCILU);
8278      PCFactorSeUseInPlace(pc);
8279 .ve
8280   or by using the options -pc_type ilu -pc_factor_in_place
8281 
8282   In-place factorization ILU(0) can also be used as a local
8283   solver for the blocks within the block Jacobi or additive Schwarz
8284   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8285   for details on setting local solver options.
8286 
8287   Most users should employ the `KSP` interface for linear solvers
8288   instead of working directly with matrix algebra routines such as this.
8289   See, e.g., `KSPCreate()`.
8290 
8291 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8292 @*/
8293 PetscErrorCode MatSetUnfactored(Mat mat)
8294 {
8295   PetscFunctionBegin;
8296   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8297   PetscValidType(mat, 1);
8298   MatCheckPreallocated(mat, 1);
8299   mat->factortype = MAT_FACTOR_NONE;
8300   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8301   PetscUseTypeMethod(mat, setunfactored);
8302   PetscFunctionReturn(PETSC_SUCCESS);
8303 }
8304 
8305 /*@
8306   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8307   as the original matrix.
8308 
8309   Collective
8310 
8311   Input Parameters:
8312 + mat   - the original matrix
8313 . isrow - parallel `IS` containing the rows this processor should obtain
8314 . 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.
8315 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8316 
8317   Output Parameter:
8318 . newmat - the new submatrix, of the same type as the original matrix
8319 
8320   Level: advanced
8321 
8322   Notes:
8323   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8324 
8325   Some matrix types place restrictions on the row and column indices, such
8326   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;
8327   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8328 
8329   The index sets may not have duplicate entries.
8330 
8331   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8332   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8333   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8334   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8335   you are finished using it.
8336 
8337   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8338   the input matrix.
8339 
8340   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8341 
8342   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8343   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8344 
8345   Example usage:
8346   Consider the following 8x8 matrix with 34 non-zero values, that is
8347   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8348   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8349   as follows
8350 .vb
8351             1  2  0  |  0  3  0  |  0  4
8352     Proc0   0  5  6  |  7  0  0  |  8  0
8353             9  0 10  | 11  0  0  | 12  0
8354     -------------------------------------
8355            13  0 14  | 15 16 17  |  0  0
8356     Proc1   0 18  0  | 19 20 21  |  0  0
8357             0  0  0  | 22 23  0  | 24  0
8358     -------------------------------------
8359     Proc2  25 26 27  |  0  0 28  | 29  0
8360            30  0  0  | 31 32 33  |  0 34
8361 .ve
8362 
8363   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8364 
8365 .vb
8366             2  0  |  0  3  0  |  0
8367     Proc0   5  6  |  7  0  0  |  8
8368     -------------------------------
8369     Proc1  18  0  | 19 20 21  |  0
8370     -------------------------------
8371     Proc2  26 27  |  0  0 28  | 29
8372             0  0  | 31 32 33  |  0
8373 .ve
8374 
8375 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8376 @*/
8377 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8378 {
8379   PetscMPIInt size;
8380   Mat        *local;
8381   IS          iscoltmp;
8382   PetscBool   flg;
8383 
8384   PetscFunctionBegin;
8385   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8386   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8387   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8388   PetscAssertPointer(newmat, 5);
8389   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8390   PetscValidType(mat, 1);
8391   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8392   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8393 
8394   MatCheckPreallocated(mat, 1);
8395   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8396 
8397   if (!iscol || isrow == iscol) {
8398     PetscBool   stride;
8399     PetscMPIInt grabentirematrix = 0, grab;
8400     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8401     if (stride) {
8402       PetscInt first, step, n, rstart, rend;
8403       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8404       if (step == 1) {
8405         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8406         if (rstart == first) {
8407           PetscCall(ISGetLocalSize(isrow, &n));
8408           if (n == rend - rstart) grabentirematrix = 1;
8409         }
8410       }
8411     }
8412     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8413     if (grab) {
8414       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8415       if (cll == MAT_INITIAL_MATRIX) {
8416         *newmat = mat;
8417         PetscCall(PetscObjectReference((PetscObject)mat));
8418       }
8419       PetscFunctionReturn(PETSC_SUCCESS);
8420     }
8421   }
8422 
8423   if (!iscol) {
8424     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8425   } else {
8426     iscoltmp = iscol;
8427   }
8428 
8429   /* if original matrix is on just one processor then use submatrix generated */
8430   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8431     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8432     goto setproperties;
8433   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8434     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8435     *newmat = *local;
8436     PetscCall(PetscFree(local));
8437     goto setproperties;
8438   } else if (!mat->ops->createsubmatrix) {
8439     /* Create a new matrix type that implements the operation using the full matrix */
8440     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8441     switch (cll) {
8442     case MAT_INITIAL_MATRIX:
8443       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8444       break;
8445     case MAT_REUSE_MATRIX:
8446       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8447       break;
8448     default:
8449       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8450     }
8451     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8452     goto setproperties;
8453   }
8454 
8455   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8456   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8457   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8458 
8459 setproperties:
8460   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8461     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8462     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8463   }
8464   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8465   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8466   PetscFunctionReturn(PETSC_SUCCESS);
8467 }
8468 
8469 /*@
8470   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8471 
8472   Not Collective
8473 
8474   Input Parameters:
8475 + A - the matrix we wish to propagate options from
8476 - B - the matrix we wish to propagate options to
8477 
8478   Level: beginner
8479 
8480   Note:
8481   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8482 
8483 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8484 @*/
8485 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8486 {
8487   PetscFunctionBegin;
8488   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8489   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8490   B->symmetry_eternal            = A->symmetry_eternal;
8491   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8492   B->symmetric                   = A->symmetric;
8493   B->structurally_symmetric      = A->structurally_symmetric;
8494   B->spd                         = A->spd;
8495   B->hermitian                   = A->hermitian;
8496   PetscFunctionReturn(PETSC_SUCCESS);
8497 }
8498 
8499 /*@
8500   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8501   used during the assembly process to store values that belong to
8502   other processors.
8503 
8504   Not Collective
8505 
8506   Input Parameters:
8507 + mat   - the matrix
8508 . size  - the initial size of the stash.
8509 - bsize - the initial size of the block-stash(if used).
8510 
8511   Options Database Keys:
8512 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8513 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8514 
8515   Level: intermediate
8516 
8517   Notes:
8518   The block-stash is used for values set with `MatSetValuesBlocked()` while
8519   the stash is used for values set with `MatSetValues()`
8520 
8521   Run with the option -info and look for output of the form
8522   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8523   to determine the appropriate value, MM, to use for size and
8524   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8525   to determine the value, BMM to use for bsize
8526 
8527 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8528 @*/
8529 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8530 {
8531   PetscFunctionBegin;
8532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8533   PetscValidType(mat, 1);
8534   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8535   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8536   PetscFunctionReturn(PETSC_SUCCESS);
8537 }
8538 
8539 /*@
8540   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8541   the matrix
8542 
8543   Neighbor-wise Collective
8544 
8545   Input Parameters:
8546 + A - the matrix
8547 . x - the vector to be multiplied by the interpolation operator
8548 - y - the vector to be added to the result
8549 
8550   Output Parameter:
8551 . w - the resulting vector
8552 
8553   Level: intermediate
8554 
8555   Notes:
8556   `w` may be the same vector as `y`.
8557 
8558   This allows one to use either the restriction or interpolation (its transpose)
8559   matrix to do the interpolation
8560 
8561 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8562 @*/
8563 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8564 {
8565   PetscInt M, N, Ny;
8566 
8567   PetscFunctionBegin;
8568   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8569   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8570   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8571   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8572   PetscCall(MatGetSize(A, &M, &N));
8573   PetscCall(VecGetSize(y, &Ny));
8574   if (M == Ny) {
8575     PetscCall(MatMultAdd(A, x, y, w));
8576   } else {
8577     PetscCall(MatMultTransposeAdd(A, x, y, w));
8578   }
8579   PetscFunctionReturn(PETSC_SUCCESS);
8580 }
8581 
8582 /*@
8583   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8584   the matrix
8585 
8586   Neighbor-wise Collective
8587 
8588   Input Parameters:
8589 + A - the matrix
8590 - x - the vector to be interpolated
8591 
8592   Output Parameter:
8593 . y - the resulting vector
8594 
8595   Level: intermediate
8596 
8597   Note:
8598   This allows one to use either the restriction or interpolation (its transpose)
8599   matrix to do the interpolation
8600 
8601 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8602 @*/
8603 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8604 {
8605   PetscInt M, N, Ny;
8606 
8607   PetscFunctionBegin;
8608   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8609   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8610   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8611   PetscCall(MatGetSize(A, &M, &N));
8612   PetscCall(VecGetSize(y, &Ny));
8613   if (M == Ny) {
8614     PetscCall(MatMult(A, x, y));
8615   } else {
8616     PetscCall(MatMultTranspose(A, x, y));
8617   }
8618   PetscFunctionReturn(PETSC_SUCCESS);
8619 }
8620 
8621 /*@
8622   MatRestrict - $y = A*x$ or $A^T*x$
8623 
8624   Neighbor-wise Collective
8625 
8626   Input Parameters:
8627 + A - the matrix
8628 - x - the vector to be restricted
8629 
8630   Output Parameter:
8631 . y - the resulting vector
8632 
8633   Level: intermediate
8634 
8635   Note:
8636   This allows one to use either the restriction or interpolation (its transpose)
8637   matrix to do the restriction
8638 
8639 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8640 @*/
8641 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8642 {
8643   PetscInt M, N, Nx;
8644 
8645   PetscFunctionBegin;
8646   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8647   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8648   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8649   PetscCall(MatGetSize(A, &M, &N));
8650   PetscCall(VecGetSize(x, &Nx));
8651   if (M == Nx) {
8652     PetscCall(MatMultTranspose(A, x, y));
8653   } else {
8654     PetscCall(MatMult(A, x, y));
8655   }
8656   PetscFunctionReturn(PETSC_SUCCESS);
8657 }
8658 
8659 /*@
8660   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8661 
8662   Neighbor-wise Collective
8663 
8664   Input Parameters:
8665 + A - the matrix
8666 . x - the input dense matrix to be multiplied
8667 - w - the input dense matrix to be added to the result
8668 
8669   Output Parameter:
8670 . y - the output dense matrix
8671 
8672   Level: intermediate
8673 
8674   Note:
8675   This allows one to use either the restriction or interpolation (its transpose)
8676   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8677   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8678 
8679 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8680 @*/
8681 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8682 {
8683   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8684   PetscBool trans = PETSC_TRUE;
8685   MatReuse  reuse = MAT_INITIAL_MATRIX;
8686 
8687   PetscFunctionBegin;
8688   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8689   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8690   PetscValidType(x, 2);
8691   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8692   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8693   PetscCall(MatGetSize(A, &M, &N));
8694   PetscCall(MatGetSize(x, &Mx, &Nx));
8695   if (N == Mx) trans = PETSC_FALSE;
8696   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);
8697   Mo = trans ? N : M;
8698   if (*y) {
8699     PetscCall(MatGetSize(*y, &My, &Ny));
8700     if (Mo == My && Nx == Ny) {
8701       reuse = MAT_REUSE_MATRIX;
8702     } else {
8703       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);
8704       PetscCall(MatDestroy(y));
8705     }
8706   }
8707 
8708   if (w && *y == w) { /* this is to minimize changes in PCMG */
8709     PetscBool flg;
8710 
8711     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8712     if (w) {
8713       PetscInt My, Ny, Mw, Nw;
8714 
8715       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8716       PetscCall(MatGetSize(*y, &My, &Ny));
8717       PetscCall(MatGetSize(w, &Mw, &Nw));
8718       if (!flg || My != Mw || Ny != Nw) w = NULL;
8719     }
8720     if (!w) {
8721       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8722       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8723       PetscCall(PetscObjectDereference((PetscObject)w));
8724     } else {
8725       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8726     }
8727   }
8728   if (!trans) {
8729     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8730   } else {
8731     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8732   }
8733   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8734   PetscFunctionReturn(PETSC_SUCCESS);
8735 }
8736 
8737 /*@
8738   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8739 
8740   Neighbor-wise Collective
8741 
8742   Input Parameters:
8743 + A - the matrix
8744 - x - the input dense matrix
8745 
8746   Output Parameter:
8747 . y - the output dense matrix
8748 
8749   Level: intermediate
8750 
8751   Note:
8752   This allows one to use either the restriction or interpolation (its transpose)
8753   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8754   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8755 
8756 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8757 @*/
8758 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8759 {
8760   PetscFunctionBegin;
8761   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8762   PetscFunctionReturn(PETSC_SUCCESS);
8763 }
8764 
8765 /*@
8766   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8767 
8768   Neighbor-wise Collective
8769 
8770   Input Parameters:
8771 + A - the matrix
8772 - x - the input dense matrix
8773 
8774   Output Parameter:
8775 . y - the output dense matrix
8776 
8777   Level: intermediate
8778 
8779   Note:
8780   This allows one to use either the restriction or interpolation (its transpose)
8781   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8782   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8783 
8784 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8785 @*/
8786 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8787 {
8788   PetscFunctionBegin;
8789   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8790   PetscFunctionReturn(PETSC_SUCCESS);
8791 }
8792 
8793 /*@
8794   MatGetNullSpace - retrieves the null space of a matrix.
8795 
8796   Logically Collective
8797 
8798   Input Parameters:
8799 + mat    - the matrix
8800 - nullsp - the null space object
8801 
8802   Level: developer
8803 
8804 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8805 @*/
8806 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8807 {
8808   PetscFunctionBegin;
8809   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8810   PetscAssertPointer(nullsp, 2);
8811   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8812   PetscFunctionReturn(PETSC_SUCCESS);
8813 }
8814 
8815 /*@C
8816   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8817 
8818   Logically Collective
8819 
8820   Input Parameters:
8821 + n   - the number of matrices
8822 - mat - the array of matrices
8823 
8824   Output Parameters:
8825 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8826 
8827   Level: developer
8828 
8829   Note:
8830   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8831 
8832 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8833           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8834 @*/
8835 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8836 {
8837   PetscFunctionBegin;
8838   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8839   PetscAssertPointer(mat, 2);
8840   PetscAssertPointer(nullsp, 3);
8841 
8842   PetscCall(PetscCalloc1(3 * n, nullsp));
8843   for (PetscInt i = 0; i < n; i++) {
8844     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8845     (*nullsp)[i] = mat[i]->nullsp;
8846     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8847     (*nullsp)[n + i] = mat[i]->nearnullsp;
8848     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8849     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8850     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8851   }
8852   PetscFunctionReturn(PETSC_SUCCESS);
8853 }
8854 
8855 /*@C
8856   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8857 
8858   Logically Collective
8859 
8860   Input Parameters:
8861 + n      - the number of matrices
8862 . mat    - the array of matrices
8863 - nullsp - an array of null spaces
8864 
8865   Level: developer
8866 
8867   Note:
8868   Call `MatGetNullSpaces()` to create `nullsp`
8869 
8870 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8871           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8872 @*/
8873 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8874 {
8875   PetscFunctionBegin;
8876   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8877   PetscAssertPointer(mat, 2);
8878   PetscAssertPointer(nullsp, 3);
8879   PetscAssertPointer(*nullsp, 3);
8880 
8881   for (PetscInt i = 0; i < n; i++) {
8882     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8883     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8884     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8885     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8886     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8887     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8888     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8889   }
8890   PetscCall(PetscFree(*nullsp));
8891   PetscFunctionReturn(PETSC_SUCCESS);
8892 }
8893 
8894 /*@
8895   MatSetNullSpace - attaches a null space to a matrix.
8896 
8897   Logically Collective
8898 
8899   Input Parameters:
8900 + mat    - the matrix
8901 - nullsp - the null space object
8902 
8903   Level: advanced
8904 
8905   Notes:
8906   This null space is used by the `KSP` linear solvers to solve singular systems.
8907 
8908   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`
8909 
8910   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
8911   to zero but the linear system will still be solved in a least squares sense.
8912 
8913   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8914   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)$, plus the range of $A^T$, $R(A^T)$.
8915   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
8916   $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
8917   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)$.
8918   This  $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8919 
8920   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called
8921   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8922   routine also automatically calls `MatSetTransposeNullSpace()`.
8923 
8924   The user should call `MatNullSpaceDestroy()`.
8925 
8926 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8927           `KSPSetPCSide()`
8928 @*/
8929 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8930 {
8931   PetscFunctionBegin;
8932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8933   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8934   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8935   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8936   mat->nullsp = nullsp;
8937   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8938   PetscFunctionReturn(PETSC_SUCCESS);
8939 }
8940 
8941 /*@
8942   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8943 
8944   Logically Collective
8945 
8946   Input Parameters:
8947 + mat    - the matrix
8948 - nullsp - the null space object
8949 
8950   Level: developer
8951 
8952 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8953 @*/
8954 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8955 {
8956   PetscFunctionBegin;
8957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8958   PetscValidType(mat, 1);
8959   PetscAssertPointer(nullsp, 2);
8960   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8961   PetscFunctionReturn(PETSC_SUCCESS);
8962 }
8963 
8964 /*@
8965   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8966 
8967   Logically Collective
8968 
8969   Input Parameters:
8970 + mat    - the matrix
8971 - nullsp - the null space object
8972 
8973   Level: advanced
8974 
8975   Notes:
8976   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8977 
8978   See `MatSetNullSpace()`
8979 
8980 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8981 @*/
8982 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8983 {
8984   PetscFunctionBegin;
8985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8986   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8987   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8988   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8989   mat->transnullsp = nullsp;
8990   PetscFunctionReturn(PETSC_SUCCESS);
8991 }
8992 
8993 /*@
8994   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8995   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8996 
8997   Logically Collective
8998 
8999   Input Parameters:
9000 + mat    - the matrix
9001 - nullsp - the null space object
9002 
9003   Level: advanced
9004 
9005   Notes:
9006   Overwrites any previous near null space that may have been attached
9007 
9008   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9009 
9010 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9011 @*/
9012 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9013 {
9014   PetscFunctionBegin;
9015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9016   PetscValidType(mat, 1);
9017   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9018   MatCheckPreallocated(mat, 1);
9019   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9020   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9021   mat->nearnullsp = nullsp;
9022   PetscFunctionReturn(PETSC_SUCCESS);
9023 }
9024 
9025 /*@
9026   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9027 
9028   Not Collective
9029 
9030   Input Parameter:
9031 . mat - the matrix
9032 
9033   Output Parameter:
9034 . nullsp - the null space object, `NULL` if not set
9035 
9036   Level: advanced
9037 
9038 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9039 @*/
9040 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9041 {
9042   PetscFunctionBegin;
9043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9044   PetscValidType(mat, 1);
9045   PetscAssertPointer(nullsp, 2);
9046   MatCheckPreallocated(mat, 1);
9047   *nullsp = mat->nearnullsp;
9048   PetscFunctionReturn(PETSC_SUCCESS);
9049 }
9050 
9051 /*@
9052   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9053 
9054   Collective
9055 
9056   Input Parameters:
9057 + mat  - the matrix
9058 . row  - row/column permutation
9059 - info - information on desired factorization process
9060 
9061   Level: developer
9062 
9063   Notes:
9064   Probably really in-place only when level of fill is zero, otherwise allocates
9065   new space to store factored matrix and deletes previous memory.
9066 
9067   Most users should employ the `KSP` interface for linear solvers
9068   instead of working directly with matrix algebra routines such as this.
9069   See, e.g., `KSPCreate()`.
9070 
9071   Fortran Note:
9072   A valid (non-null) `info` argument must be provided
9073 
9074 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9075 @*/
9076 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9077 {
9078   PetscFunctionBegin;
9079   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9080   PetscValidType(mat, 1);
9081   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9082   PetscAssertPointer(info, 3);
9083   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9084   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9085   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9086   MatCheckPreallocated(mat, 1);
9087   PetscUseTypeMethod(mat, iccfactor, row, info);
9088   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9089   PetscFunctionReturn(PETSC_SUCCESS);
9090 }
9091 
9092 /*@
9093   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9094   ghosted ones.
9095 
9096   Not Collective
9097 
9098   Input Parameters:
9099 + mat  - the matrix
9100 - diag - the diagonal values, including ghost ones
9101 
9102   Level: developer
9103 
9104   Notes:
9105   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9106 
9107   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9108 
9109 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9110 @*/
9111 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9112 {
9113   PetscMPIInt size;
9114 
9115   PetscFunctionBegin;
9116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9117   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9118   PetscValidType(mat, 1);
9119 
9120   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9121   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9122   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9123   if (size == 1) {
9124     PetscInt n, m;
9125     PetscCall(VecGetSize(diag, &n));
9126     PetscCall(MatGetSize(mat, NULL, &m));
9127     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9128     PetscCall(MatDiagonalScale(mat, NULL, diag));
9129   } else {
9130     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9131   }
9132   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9133   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9134   PetscFunctionReturn(PETSC_SUCCESS);
9135 }
9136 
9137 /*@
9138   MatGetInertia - Gets the inertia from a factored matrix
9139 
9140   Collective
9141 
9142   Input Parameter:
9143 . mat - the matrix
9144 
9145   Output Parameters:
9146 + nneg  - number of negative eigenvalues
9147 . nzero - number of zero eigenvalues
9148 - npos  - number of positive eigenvalues
9149 
9150   Level: advanced
9151 
9152   Note:
9153   Matrix must have been factored by `MatCholeskyFactor()`
9154 
9155 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9156 @*/
9157 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9158 {
9159   PetscFunctionBegin;
9160   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9161   PetscValidType(mat, 1);
9162   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9163   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9164   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9165   PetscFunctionReturn(PETSC_SUCCESS);
9166 }
9167 
9168 /*@C
9169   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9170 
9171   Neighbor-wise Collective
9172 
9173   Input Parameters:
9174 + mat - the factored matrix obtained with `MatGetFactor()`
9175 - b   - the right-hand-side vectors
9176 
9177   Output Parameter:
9178 . x - the result vectors
9179 
9180   Level: developer
9181 
9182   Note:
9183   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9184   call `MatSolves`(A,x,x).
9185 
9186 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9187 @*/
9188 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9189 {
9190   PetscFunctionBegin;
9191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9192   PetscValidType(mat, 1);
9193   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9194   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9195   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9196 
9197   MatCheckPreallocated(mat, 1);
9198   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9199   PetscUseTypeMethod(mat, solves, b, x);
9200   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9201   PetscFunctionReturn(PETSC_SUCCESS);
9202 }
9203 
9204 /*@
9205   MatIsSymmetric - Test whether a matrix is symmetric
9206 
9207   Collective
9208 
9209   Input Parameters:
9210 + A   - the matrix to test
9211 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9212 
9213   Output Parameter:
9214 . flg - the result
9215 
9216   Level: intermediate
9217 
9218   Notes:
9219   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9220 
9221   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9222 
9223   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9224   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9225 
9226 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9227           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9228 @*/
9229 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9230 {
9231   PetscFunctionBegin;
9232   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9233   PetscAssertPointer(flg, 3);
9234   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9235   else {
9236     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9237     else PetscCall(MatIsTranspose(A, A, tol, flg));
9238     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9239   }
9240   PetscFunctionReturn(PETSC_SUCCESS);
9241 }
9242 
9243 /*@
9244   MatIsHermitian - Test whether a matrix is Hermitian
9245 
9246   Collective
9247 
9248   Input Parameters:
9249 + A   - the matrix to test
9250 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9251 
9252   Output Parameter:
9253 . flg - the result
9254 
9255   Level: intermediate
9256 
9257   Notes:
9258   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9259 
9260   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9261 
9262   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9263   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9264 
9265 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9266           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9267 @*/
9268 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9269 {
9270   PetscFunctionBegin;
9271   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9272   PetscAssertPointer(flg, 3);
9273   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9274   else {
9275     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9276     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9277     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9278   }
9279   PetscFunctionReturn(PETSC_SUCCESS);
9280 }
9281 
9282 /*@
9283   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9284 
9285   Not Collective
9286 
9287   Input Parameter:
9288 . A - the matrix to check
9289 
9290   Output Parameters:
9291 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9292 - flg - the result (only valid if set is `PETSC_TRUE`)
9293 
9294   Level: advanced
9295 
9296   Notes:
9297   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9298   if you want it explicitly checked
9299 
9300   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9301   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9302 
9303 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9304 @*/
9305 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9306 {
9307   PetscFunctionBegin;
9308   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9309   PetscAssertPointer(set, 2);
9310   PetscAssertPointer(flg, 3);
9311   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9312     *set = PETSC_TRUE;
9313     *flg = PetscBool3ToBool(A->symmetric);
9314   } else {
9315     *set = PETSC_FALSE;
9316   }
9317   PetscFunctionReturn(PETSC_SUCCESS);
9318 }
9319 
9320 /*@
9321   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9322 
9323   Not Collective
9324 
9325   Input Parameter:
9326 . A - the matrix to check
9327 
9328   Output Parameters:
9329 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9330 - flg - the result (only valid if set is `PETSC_TRUE`)
9331 
9332   Level: advanced
9333 
9334   Notes:
9335   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9336 
9337   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9338   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9339 
9340 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9341 @*/
9342 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9343 {
9344   PetscFunctionBegin;
9345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9346   PetscAssertPointer(set, 2);
9347   PetscAssertPointer(flg, 3);
9348   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9349     *set = PETSC_TRUE;
9350     *flg = PetscBool3ToBool(A->spd);
9351   } else {
9352     *set = PETSC_FALSE;
9353   }
9354   PetscFunctionReturn(PETSC_SUCCESS);
9355 }
9356 
9357 /*@
9358   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9359 
9360   Not Collective
9361 
9362   Input Parameter:
9363 . A - the matrix to check
9364 
9365   Output Parameters:
9366 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9367 - flg - the result (only valid if set is `PETSC_TRUE`)
9368 
9369   Level: advanced
9370 
9371   Notes:
9372   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9373   if you want it explicitly checked
9374 
9375   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9376   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9377 
9378 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9379 @*/
9380 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9381 {
9382   PetscFunctionBegin;
9383   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9384   PetscAssertPointer(set, 2);
9385   PetscAssertPointer(flg, 3);
9386   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9387     *set = PETSC_TRUE;
9388     *flg = PetscBool3ToBool(A->hermitian);
9389   } else {
9390     *set = PETSC_FALSE;
9391   }
9392   PetscFunctionReturn(PETSC_SUCCESS);
9393 }
9394 
9395 /*@
9396   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9397 
9398   Collective
9399 
9400   Input Parameter:
9401 . A - the matrix to test
9402 
9403   Output Parameter:
9404 . flg - the result
9405 
9406   Level: intermediate
9407 
9408   Notes:
9409   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9410 
9411   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
9412   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9413 
9414 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9415 @*/
9416 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9417 {
9418   PetscFunctionBegin;
9419   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9420   PetscAssertPointer(flg, 2);
9421   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9422     *flg = PetscBool3ToBool(A->structurally_symmetric);
9423   } else {
9424     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9425     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9426   }
9427   PetscFunctionReturn(PETSC_SUCCESS);
9428 }
9429 
9430 /*@
9431   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9432 
9433   Not Collective
9434 
9435   Input Parameter:
9436 . A - the matrix to check
9437 
9438   Output Parameters:
9439 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9440 - flg - the result (only valid if set is PETSC_TRUE)
9441 
9442   Level: advanced
9443 
9444   Notes:
9445   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
9446   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9447 
9448   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9449 
9450 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9451 @*/
9452 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9453 {
9454   PetscFunctionBegin;
9455   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9456   PetscAssertPointer(set, 2);
9457   PetscAssertPointer(flg, 3);
9458   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9459     *set = PETSC_TRUE;
9460     *flg = PetscBool3ToBool(A->structurally_symmetric);
9461   } else {
9462     *set = PETSC_FALSE;
9463   }
9464   PetscFunctionReturn(PETSC_SUCCESS);
9465 }
9466 
9467 /*@
9468   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9469   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9470 
9471   Not Collective
9472 
9473   Input Parameter:
9474 . mat - the matrix
9475 
9476   Output Parameters:
9477 + nstash    - the size of the stash
9478 . reallocs  - the number of additional mallocs incurred.
9479 . bnstash   - the size of the block stash
9480 - breallocs - the number of additional mallocs incurred.in the block stash
9481 
9482   Level: advanced
9483 
9484 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9485 @*/
9486 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9487 {
9488   PetscFunctionBegin;
9489   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9490   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9491   PetscFunctionReturn(PETSC_SUCCESS);
9492 }
9493 
9494 /*@
9495   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9496   parallel layout, `PetscLayout` for rows and columns
9497 
9498   Collective
9499 
9500   Input Parameter:
9501 . mat - the matrix
9502 
9503   Output Parameters:
9504 + right - (optional) vector that the matrix can be multiplied against
9505 - left  - (optional) vector that the matrix vector product can be stored in
9506 
9507   Level: advanced
9508 
9509   Notes:
9510   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()`.
9511 
9512   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9513 
9514 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9515 @*/
9516 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9517 {
9518   PetscFunctionBegin;
9519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9520   PetscValidType(mat, 1);
9521   if (mat->ops->getvecs) {
9522     PetscUseTypeMethod(mat, getvecs, right, left);
9523   } else {
9524     if (right) {
9525       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9526       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9527       PetscCall(VecSetType(*right, mat->defaultvectype));
9528 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9529       if (mat->boundtocpu && mat->bindingpropagates) {
9530         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9531         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9532       }
9533 #endif
9534     }
9535     if (left) {
9536       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9537       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9538       PetscCall(VecSetType(*left, mat->defaultvectype));
9539 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9540       if (mat->boundtocpu && mat->bindingpropagates) {
9541         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9542         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9543       }
9544 #endif
9545     }
9546   }
9547   PetscFunctionReturn(PETSC_SUCCESS);
9548 }
9549 
9550 /*@
9551   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9552   with default values.
9553 
9554   Not Collective
9555 
9556   Input Parameter:
9557 . info - the `MatFactorInfo` data structure
9558 
9559   Level: developer
9560 
9561   Notes:
9562   The solvers are generally used through the `KSP` and `PC` objects, for example
9563   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9564 
9565   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9566 
9567 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9568 @*/
9569 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9570 {
9571   PetscFunctionBegin;
9572   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9573   PetscFunctionReturn(PETSC_SUCCESS);
9574 }
9575 
9576 /*@
9577   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9578 
9579   Collective
9580 
9581   Input Parameters:
9582 + mat - the factored matrix
9583 - is  - the index set defining the Schur indices (0-based)
9584 
9585   Level: advanced
9586 
9587   Notes:
9588   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9589 
9590   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9591 
9592   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9593 
9594 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9595           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9596 @*/
9597 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9598 {
9599   PetscErrorCode (*f)(Mat, IS);
9600 
9601   PetscFunctionBegin;
9602   PetscValidType(mat, 1);
9603   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9604   PetscValidType(is, 2);
9605   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9606   PetscCheckSameComm(mat, 1, is, 2);
9607   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9608   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9609   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9610   PetscCall(MatDestroy(&mat->schur));
9611   PetscCall((*f)(mat, is));
9612   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9613   PetscFunctionReturn(PETSC_SUCCESS);
9614 }
9615 
9616 /*@
9617   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9618 
9619   Logically Collective
9620 
9621   Input Parameters:
9622 + F      - the factored matrix obtained by calling `MatGetFactor()`
9623 . S      - location where to return the Schur complement, can be `NULL`
9624 - status - the status of the Schur complement matrix, can be `NULL`
9625 
9626   Level: advanced
9627 
9628   Notes:
9629   You must call `MatFactorSetSchurIS()` before calling this routine.
9630 
9631   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9632 
9633   The routine provides a copy of the Schur matrix stored within the solver data structures.
9634   The caller must destroy the object when it is no longer needed.
9635   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9636 
9637   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)
9638 
9639   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9640 
9641   Developer Note:
9642   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9643   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9644 
9645 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9646 @*/
9647 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9648 {
9649   PetscFunctionBegin;
9650   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9651   if (S) PetscAssertPointer(S, 2);
9652   if (status) PetscAssertPointer(status, 3);
9653   if (S) {
9654     PetscErrorCode (*f)(Mat, Mat *);
9655 
9656     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9657     if (f) {
9658       PetscCall((*f)(F, S));
9659     } else {
9660       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9661     }
9662   }
9663   if (status) *status = F->schur_status;
9664   PetscFunctionReturn(PETSC_SUCCESS);
9665 }
9666 
9667 /*@
9668   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9669 
9670   Logically Collective
9671 
9672   Input Parameters:
9673 + F      - the factored matrix obtained by calling `MatGetFactor()`
9674 . S      - location where to return the Schur complement, can be `NULL`
9675 - status - the status of the Schur complement matrix, can be `NULL`
9676 
9677   Level: advanced
9678 
9679   Notes:
9680   You must call `MatFactorSetSchurIS()` before calling this routine.
9681 
9682   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9683 
9684   The routine returns a the Schur Complement stored within the data structures of the solver.
9685 
9686   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9687 
9688   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9689 
9690   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9691 
9692   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9693 
9694 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9695 @*/
9696 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9697 {
9698   PetscFunctionBegin;
9699   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9700   if (S) {
9701     PetscAssertPointer(S, 2);
9702     *S = F->schur;
9703   }
9704   if (status) {
9705     PetscAssertPointer(status, 3);
9706     *status = F->schur_status;
9707   }
9708   PetscFunctionReturn(PETSC_SUCCESS);
9709 }
9710 
9711 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9712 {
9713   Mat S = F->schur;
9714 
9715   PetscFunctionBegin;
9716   switch (F->schur_status) {
9717   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9718   case MAT_FACTOR_SCHUR_INVERTED:
9719     if (S) {
9720       S->ops->solve             = NULL;
9721       S->ops->matsolve          = NULL;
9722       S->ops->solvetranspose    = NULL;
9723       S->ops->matsolvetranspose = NULL;
9724       S->ops->solveadd          = NULL;
9725       S->ops->solvetransposeadd = NULL;
9726       S->factortype             = MAT_FACTOR_NONE;
9727       PetscCall(PetscFree(S->solvertype));
9728     }
9729   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9730     break;
9731   default:
9732     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9733   }
9734   PetscFunctionReturn(PETSC_SUCCESS);
9735 }
9736 
9737 /*@
9738   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9739 
9740   Logically Collective
9741 
9742   Input Parameters:
9743 + F      - the factored matrix obtained by calling `MatGetFactor()`
9744 . S      - location where the Schur complement is stored
9745 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9746 
9747   Level: advanced
9748 
9749 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9750 @*/
9751 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9752 {
9753   PetscFunctionBegin;
9754   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9755   if (S) {
9756     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9757     *S = NULL;
9758   }
9759   F->schur_status = status;
9760   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9761   PetscFunctionReturn(PETSC_SUCCESS);
9762 }
9763 
9764 /*@
9765   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9766 
9767   Logically Collective
9768 
9769   Input Parameters:
9770 + F   - the factored matrix obtained by calling `MatGetFactor()`
9771 . rhs - location where the right-hand side of the Schur complement system is stored
9772 - sol - location where the solution of the Schur complement system has to be returned
9773 
9774   Level: advanced
9775 
9776   Notes:
9777   The sizes of the vectors should match the size of the Schur complement
9778 
9779   Must be called after `MatFactorSetSchurIS()`
9780 
9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9782 @*/
9783 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9784 {
9785   PetscFunctionBegin;
9786   PetscValidType(F, 1);
9787   PetscValidType(rhs, 2);
9788   PetscValidType(sol, 3);
9789   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9790   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9791   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9792   PetscCheckSameComm(F, 1, rhs, 2);
9793   PetscCheckSameComm(F, 1, sol, 3);
9794   PetscCall(MatFactorFactorizeSchurComplement(F));
9795   switch (F->schur_status) {
9796   case MAT_FACTOR_SCHUR_FACTORED:
9797     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9798     break;
9799   case MAT_FACTOR_SCHUR_INVERTED:
9800     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9801     break;
9802   default:
9803     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9804   }
9805   PetscFunctionReturn(PETSC_SUCCESS);
9806 }
9807 
9808 /*@
9809   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9810 
9811   Logically Collective
9812 
9813   Input Parameters:
9814 + F   - the factored matrix obtained by calling `MatGetFactor()`
9815 . rhs - location where the right-hand side of the Schur complement system is stored
9816 - sol - location where the solution of the Schur complement system has to be returned
9817 
9818   Level: advanced
9819 
9820   Notes:
9821   The sizes of the vectors should match the size of the Schur complement
9822 
9823   Must be called after `MatFactorSetSchurIS()`
9824 
9825 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9826 @*/
9827 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9828 {
9829   PetscFunctionBegin;
9830   PetscValidType(F, 1);
9831   PetscValidType(rhs, 2);
9832   PetscValidType(sol, 3);
9833   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9834   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9835   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9836   PetscCheckSameComm(F, 1, rhs, 2);
9837   PetscCheckSameComm(F, 1, sol, 3);
9838   PetscCall(MatFactorFactorizeSchurComplement(F));
9839   switch (F->schur_status) {
9840   case MAT_FACTOR_SCHUR_FACTORED:
9841     PetscCall(MatSolve(F->schur, rhs, sol));
9842     break;
9843   case MAT_FACTOR_SCHUR_INVERTED:
9844     PetscCall(MatMult(F->schur, rhs, sol));
9845     break;
9846   default:
9847     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9848   }
9849   PetscFunctionReturn(PETSC_SUCCESS);
9850 }
9851 
9852 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9853 #if PetscDefined(HAVE_CUDA)
9854 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9855 #endif
9856 
9857 /* Schur status updated in the interface */
9858 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9859 {
9860   Mat S = F->schur;
9861 
9862   PetscFunctionBegin;
9863   if (S) {
9864     PetscMPIInt size;
9865     PetscBool   isdense, isdensecuda;
9866 
9867     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9868     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9869     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9870     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9871     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9872     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9873     if (isdense) {
9874       PetscCall(MatSeqDenseInvertFactors_Private(S));
9875     } else if (isdensecuda) {
9876 #if defined(PETSC_HAVE_CUDA)
9877       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9878 #endif
9879     }
9880     // HIP??????????????
9881     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9882   }
9883   PetscFunctionReturn(PETSC_SUCCESS);
9884 }
9885 
9886 /*@
9887   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9888 
9889   Logically Collective
9890 
9891   Input Parameter:
9892 . F - the factored matrix obtained by calling `MatGetFactor()`
9893 
9894   Level: advanced
9895 
9896   Notes:
9897   Must be called after `MatFactorSetSchurIS()`.
9898 
9899   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9900 
9901 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9902 @*/
9903 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9904 {
9905   PetscFunctionBegin;
9906   PetscValidType(F, 1);
9907   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9908   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9909   PetscCall(MatFactorFactorizeSchurComplement(F));
9910   PetscCall(MatFactorInvertSchurComplement_Private(F));
9911   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9912   PetscFunctionReturn(PETSC_SUCCESS);
9913 }
9914 
9915 /*@
9916   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9917 
9918   Logically Collective
9919 
9920   Input Parameter:
9921 . F - the factored matrix obtained by calling `MatGetFactor()`
9922 
9923   Level: advanced
9924 
9925   Note:
9926   Must be called after `MatFactorSetSchurIS()`
9927 
9928 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9929 @*/
9930 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9931 {
9932   MatFactorInfo info;
9933 
9934   PetscFunctionBegin;
9935   PetscValidType(F, 1);
9936   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9937   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9938   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9939   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9940   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9941     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9942   } else {
9943     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9944   }
9945   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9946   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9947   PetscFunctionReturn(PETSC_SUCCESS);
9948 }
9949 
9950 /*@
9951   MatPtAP - Creates the matrix product $C = P^T * A * P$
9952 
9953   Neighbor-wise Collective
9954 
9955   Input Parameters:
9956 + A     - the matrix
9957 . P     - the projection matrix
9958 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9959 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
9960           if the result is a dense matrix this is irrelevant
9961 
9962   Output Parameter:
9963 . C - the product matrix
9964 
9965   Level: intermediate
9966 
9967   Notes:
9968   C will be created and must be destroyed by the user with `MatDestroy()`.
9969 
9970   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9971 
9972   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
9973 
9974   Developer Note:
9975   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9976 
9977 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9978 @*/
9979 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9980 {
9981   PetscFunctionBegin;
9982   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9983   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9984 
9985   if (scall == MAT_INITIAL_MATRIX) {
9986     PetscCall(MatProductCreate(A, P, NULL, C));
9987     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9988     PetscCall(MatProductSetAlgorithm(*C, "default"));
9989     PetscCall(MatProductSetFill(*C, fill));
9990 
9991     (*C)->product->api_user = PETSC_TRUE;
9992     PetscCall(MatProductSetFromOptions(*C));
9993     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);
9994     PetscCall(MatProductSymbolic(*C));
9995   } else { /* scall == MAT_REUSE_MATRIX */
9996     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9997   }
9998 
9999   PetscCall(MatProductNumeric(*C));
10000   (*C)->symmetric = A->symmetric;
10001   (*C)->spd       = A->spd;
10002   PetscFunctionReturn(PETSC_SUCCESS);
10003 }
10004 
10005 /*@
10006   MatRARt - Creates the matrix product $C = R * A * R^T$
10007 
10008   Neighbor-wise Collective
10009 
10010   Input Parameters:
10011 + A     - the matrix
10012 . R     - the projection matrix
10013 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10014 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10015           if the result is a dense matrix this is irrelevant
10016 
10017   Output Parameter:
10018 . C - the product matrix
10019 
10020   Level: intermediate
10021 
10022   Notes:
10023   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10024 
10025   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10026 
10027   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10028   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10029   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10030   We recommend using `MatPtAP()` when possible.
10031 
10032   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10033 
10034 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10035 @*/
10036 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10037 {
10038   PetscFunctionBegin;
10039   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10040   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10041 
10042   if (scall == MAT_INITIAL_MATRIX) {
10043     PetscCall(MatProductCreate(A, R, NULL, C));
10044     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10045     PetscCall(MatProductSetAlgorithm(*C, "default"));
10046     PetscCall(MatProductSetFill(*C, fill));
10047 
10048     (*C)->product->api_user = PETSC_TRUE;
10049     PetscCall(MatProductSetFromOptions(*C));
10050     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);
10051     PetscCall(MatProductSymbolic(*C));
10052   } else { /* scall == MAT_REUSE_MATRIX */
10053     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10054   }
10055 
10056   PetscCall(MatProductNumeric(*C));
10057   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10058   PetscFunctionReturn(PETSC_SUCCESS);
10059 }
10060 
10061 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10062 {
10063   PetscBool flg = PETSC_TRUE;
10064 
10065   PetscFunctionBegin;
10066   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10067   if (scall == MAT_INITIAL_MATRIX) {
10068     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10069     PetscCall(MatProductCreate(A, B, NULL, C));
10070     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10071     PetscCall(MatProductSetFill(*C, fill));
10072   } else { /* scall == MAT_REUSE_MATRIX */
10073     Mat_Product *product = (*C)->product;
10074 
10075     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10076     if (flg && product && product->type != ptype) {
10077       PetscCall(MatProductClear(*C));
10078       product = NULL;
10079     }
10080     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10081     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10082       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10083       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10084       product        = (*C)->product;
10085       product->fill  = fill;
10086       product->clear = PETSC_TRUE;
10087     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10088       flg = PETSC_FALSE;
10089       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10090     }
10091   }
10092   if (flg) {
10093     (*C)->product->api_user = PETSC_TRUE;
10094     PetscCall(MatProductSetType(*C, ptype));
10095     PetscCall(MatProductSetFromOptions(*C));
10096     PetscCall(MatProductSymbolic(*C));
10097   }
10098   PetscCall(MatProductNumeric(*C));
10099   PetscFunctionReturn(PETSC_SUCCESS);
10100 }
10101 
10102 /*@
10103   MatMatMult - Performs matrix-matrix multiplication C=A*B.
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_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10112           if the result is a dense matrix this is irrelevant
10113 
10114   Output Parameter:
10115 . C - the product matrix
10116 
10117   Notes:
10118   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10119 
10120   `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
10121   call to this function with `MAT_INITIAL_MATRIX`.
10122 
10123   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10124 
10125   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`,
10126   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10127 
10128   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10129 
10130   Example of Usage:
10131 .vb
10132      MatProductCreate(A,B,NULL,&C);
10133      MatProductSetType(C,MATPRODUCT_AB);
10134      MatProductSymbolic(C);
10135      MatProductNumeric(C); // compute C=A * B
10136      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10137      MatProductNumeric(C);
10138      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10139      MatProductNumeric(C);
10140 .ve
10141 
10142   Level: intermediate
10143 
10144 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10145 @*/
10146 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10147 {
10148   PetscFunctionBegin;
10149   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10150   PetscFunctionReturn(PETSC_SUCCESS);
10151 }
10152 
10153 /*@
10154   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10155 
10156   Neighbor-wise Collective
10157 
10158   Input Parameters:
10159 + A     - the left matrix
10160 . B     - the right matrix
10161 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10162 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10163 
10164   Output Parameter:
10165 . C - the product matrix
10166 
10167   Options Database Key:
10168 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10169               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10170               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10171 
10172   Level: intermediate
10173 
10174   Notes:
10175   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10176 
10177   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10178 
10179   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10180   actually needed.
10181 
10182   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10183   and for pairs of `MATMPIDENSE` matrices.
10184 
10185   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10186 
10187   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10188 
10189 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10190 @*/
10191 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10192 {
10193   PetscFunctionBegin;
10194   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10195   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10196   PetscFunctionReturn(PETSC_SUCCESS);
10197 }
10198 
10199 /*@
10200   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10201 
10202   Neighbor-wise Collective
10203 
10204   Input Parameters:
10205 + A     - the left matrix
10206 . B     - the right matrix
10207 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10208 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10209 
10210   Output Parameter:
10211 . C - the product matrix
10212 
10213   Level: intermediate
10214 
10215   Notes:
10216   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10217 
10218   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10219 
10220   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10221 
10222   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10223   actually needed.
10224 
10225   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10226   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10227 
10228   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10229 
10230 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10231 @*/
10232 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10233 {
10234   PetscFunctionBegin;
10235   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10236   PetscFunctionReturn(PETSC_SUCCESS);
10237 }
10238 
10239 /*@
10240   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10241 
10242   Neighbor-wise Collective
10243 
10244   Input Parameters:
10245 + A     - the left matrix
10246 . B     - the middle matrix
10247 . C     - the right matrix
10248 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10249 - fill  - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10250           if the result is a dense matrix this is irrelevant
10251 
10252   Output Parameter:
10253 . D - the product matrix
10254 
10255   Level: intermediate
10256 
10257   Notes:
10258   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10259 
10260   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10261 
10262   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10263 
10264   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10265   actually needed.
10266 
10267   If you have many matrices with the same non-zero structure to multiply, you
10268   should use `MAT_REUSE_MATRIX` in all calls but the first
10269 
10270   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10271 
10272 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10273 @*/
10274 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10275 {
10276   PetscFunctionBegin;
10277   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10278   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10279 
10280   if (scall == MAT_INITIAL_MATRIX) {
10281     PetscCall(MatProductCreate(A, B, C, D));
10282     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10283     PetscCall(MatProductSetAlgorithm(*D, "default"));
10284     PetscCall(MatProductSetFill(*D, fill));
10285 
10286     (*D)->product->api_user = PETSC_TRUE;
10287     PetscCall(MatProductSetFromOptions(*D));
10288     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,
10289                ((PetscObject)C)->type_name);
10290     PetscCall(MatProductSymbolic(*D));
10291   } else { /* user may change input matrices when REUSE */
10292     PetscCall(MatProductReplaceMats(A, B, C, *D));
10293   }
10294   PetscCall(MatProductNumeric(*D));
10295   PetscFunctionReturn(PETSC_SUCCESS);
10296 }
10297 
10298 /*@
10299   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10300 
10301   Collective
10302 
10303   Input Parameters:
10304 + mat      - the matrix
10305 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10306 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10307 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10308 
10309   Output Parameter:
10310 . matredundant - redundant matrix
10311 
10312   Level: advanced
10313 
10314   Notes:
10315   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10316   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10317 
10318   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10319   calling it.
10320 
10321   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10322 
10323 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10324 @*/
10325 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10326 {
10327   MPI_Comm       comm;
10328   PetscMPIInt    size;
10329   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10330   Mat_Redundant *redund     = NULL;
10331   PetscSubcomm   psubcomm   = NULL;
10332   MPI_Comm       subcomm_in = subcomm;
10333   Mat           *matseq;
10334   IS             isrow, iscol;
10335   PetscBool      newsubcomm = PETSC_FALSE;
10336 
10337   PetscFunctionBegin;
10338   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10339   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10340     PetscAssertPointer(*matredundant, 5);
10341     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10342   }
10343 
10344   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10345   if (size == 1 || nsubcomm == 1) {
10346     if (reuse == MAT_INITIAL_MATRIX) {
10347       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10348     } else {
10349       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");
10350       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10351     }
10352     PetscFunctionReturn(PETSC_SUCCESS);
10353   }
10354 
10355   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10356   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10357   MatCheckPreallocated(mat, 1);
10358 
10359   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10360   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10361     /* create psubcomm, then get subcomm */
10362     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10363     PetscCallMPI(MPI_Comm_size(comm, &size));
10364     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10365 
10366     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10367     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10368     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10369     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10370     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10371     newsubcomm = PETSC_TRUE;
10372     PetscCall(PetscSubcommDestroy(&psubcomm));
10373   }
10374 
10375   /* get isrow, iscol and a local sequential matrix matseq[0] */
10376   if (reuse == MAT_INITIAL_MATRIX) {
10377     mloc_sub = PETSC_DECIDE;
10378     nloc_sub = PETSC_DECIDE;
10379     if (bs < 1) {
10380       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10381       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10382     } else {
10383       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10384       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10385     }
10386     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10387     rstart = rend - mloc_sub;
10388     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10389     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10390     PetscCall(ISSetIdentity(iscol));
10391   } else { /* reuse == MAT_REUSE_MATRIX */
10392     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");
10393     /* retrieve subcomm */
10394     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10395     redund = (*matredundant)->redundant;
10396     isrow  = redund->isrow;
10397     iscol  = redund->iscol;
10398     matseq = redund->matseq;
10399   }
10400   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10401 
10402   /* get matredundant over subcomm */
10403   if (reuse == MAT_INITIAL_MATRIX) {
10404     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10405 
10406     /* create a supporting struct and attach it to C for reuse */
10407     PetscCall(PetscNew(&redund));
10408     (*matredundant)->redundant = redund;
10409     redund->isrow              = isrow;
10410     redund->iscol              = iscol;
10411     redund->matseq             = matseq;
10412     if (newsubcomm) {
10413       redund->subcomm = subcomm;
10414     } else {
10415       redund->subcomm = MPI_COMM_NULL;
10416     }
10417   } else {
10418     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10419   }
10420 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10421   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10422     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10423     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10424   }
10425 #endif
10426   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10427   PetscFunctionReturn(PETSC_SUCCESS);
10428 }
10429 
10430 /*@C
10431   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10432   a given `Mat`. Each submatrix can span multiple procs.
10433 
10434   Collective
10435 
10436   Input Parameters:
10437 + mat     - the matrix
10438 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10439 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10440 
10441   Output Parameter:
10442 . subMat - parallel sub-matrices each spanning a given `subcomm`
10443 
10444   Level: advanced
10445 
10446   Notes:
10447   The submatrix partition across processors is dictated by `subComm` a
10448   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10449   is not restricted to be grouped with consecutive original MPI processes.
10450 
10451   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10452   map directly to the layout of the original matrix [wrt the local
10453   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10454   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10455   the `subMat`. However the offDiagMat looses some columns - and this is
10456   reconstructed with `MatSetValues()`
10457 
10458   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10459 
10460 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10461 @*/
10462 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10463 {
10464   PetscMPIInt commsize, subCommSize;
10465 
10466   PetscFunctionBegin;
10467   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10468   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10469   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10470 
10471   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");
10472   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10473   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10474   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10475   PetscFunctionReturn(PETSC_SUCCESS);
10476 }
10477 
10478 /*@
10479   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10480 
10481   Not Collective
10482 
10483   Input Parameters:
10484 + mat   - matrix to extract local submatrix from
10485 . isrow - local row indices for submatrix
10486 - iscol - local column indices for submatrix
10487 
10488   Output Parameter:
10489 . submat - the submatrix
10490 
10491   Level: intermediate
10492 
10493   Notes:
10494   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10495 
10496   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10497   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10498 
10499   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10500   `MatSetValuesBlockedLocal()` will also be implemented.
10501 
10502   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10503   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10504 
10505 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10506 @*/
10507 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10508 {
10509   PetscFunctionBegin;
10510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10511   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10512   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10513   PetscCheckSameComm(isrow, 2, iscol, 3);
10514   PetscAssertPointer(submat, 4);
10515   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10516 
10517   if (mat->ops->getlocalsubmatrix) {
10518     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10519   } else {
10520     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10521   }
10522   PetscFunctionReturn(PETSC_SUCCESS);
10523 }
10524 
10525 /*@
10526   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10527 
10528   Not Collective
10529 
10530   Input Parameters:
10531 + mat    - matrix to extract local submatrix from
10532 . isrow  - local row indices for submatrix
10533 . iscol  - local column indices for submatrix
10534 - submat - the submatrix
10535 
10536   Level: intermediate
10537 
10538 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10539 @*/
10540 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10541 {
10542   PetscFunctionBegin;
10543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10544   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10545   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10546   PetscCheckSameComm(isrow, 2, iscol, 3);
10547   PetscAssertPointer(submat, 4);
10548   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10549 
10550   if (mat->ops->restorelocalsubmatrix) {
10551     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10552   } else {
10553     PetscCall(MatDestroy(submat));
10554   }
10555   *submat = NULL;
10556   PetscFunctionReturn(PETSC_SUCCESS);
10557 }
10558 
10559 /*@
10560   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10561 
10562   Collective
10563 
10564   Input Parameter:
10565 . mat - the matrix
10566 
10567   Output Parameter:
10568 . is - if any rows have zero diagonals this contains the list of them
10569 
10570   Level: developer
10571 
10572 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10573 @*/
10574 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10575 {
10576   PetscFunctionBegin;
10577   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10578   PetscValidType(mat, 1);
10579   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10581 
10582   if (!mat->ops->findzerodiagonals) {
10583     Vec                diag;
10584     const PetscScalar *a;
10585     PetscInt          *rows;
10586     PetscInt           rStart, rEnd, r, nrow = 0;
10587 
10588     PetscCall(MatCreateVecs(mat, &diag, NULL));
10589     PetscCall(MatGetDiagonal(mat, diag));
10590     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10591     PetscCall(VecGetArrayRead(diag, &a));
10592     for (r = 0; r < rEnd - rStart; ++r)
10593       if (a[r] == 0.0) ++nrow;
10594     PetscCall(PetscMalloc1(nrow, &rows));
10595     nrow = 0;
10596     for (r = 0; r < rEnd - rStart; ++r)
10597       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10598     PetscCall(VecRestoreArrayRead(diag, &a));
10599     PetscCall(VecDestroy(&diag));
10600     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10601   } else {
10602     PetscUseTypeMethod(mat, findzerodiagonals, is);
10603   }
10604   PetscFunctionReturn(PETSC_SUCCESS);
10605 }
10606 
10607 /*@
10608   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10609 
10610   Collective
10611 
10612   Input Parameter:
10613 . mat - the matrix
10614 
10615   Output Parameter:
10616 . is - contains the list of rows with off block diagonal entries
10617 
10618   Level: developer
10619 
10620 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10621 @*/
10622 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10623 {
10624   PetscFunctionBegin;
10625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10626   PetscValidType(mat, 1);
10627   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10628   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10629 
10630   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10631   PetscFunctionReturn(PETSC_SUCCESS);
10632 }
10633 
10634 /*@C
10635   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10636 
10637   Collective; No Fortran Support
10638 
10639   Input Parameter:
10640 . mat - the matrix
10641 
10642   Output Parameter:
10643 . values - the block inverses in column major order (FORTRAN-like)
10644 
10645   Level: advanced
10646 
10647   Notes:
10648   The size of the blocks is determined by the block size of the matrix.
10649 
10650   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10651 
10652   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10653 
10654 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10655 @*/
10656 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10657 {
10658   PetscFunctionBegin;
10659   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10660   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10661   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10662   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10663   PetscFunctionReturn(PETSC_SUCCESS);
10664 }
10665 
10666 /*@
10667   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10668 
10669   Collective; No Fortran Support
10670 
10671   Input Parameters:
10672 + mat     - the matrix
10673 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10674 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10675 
10676   Output Parameter:
10677 . values - the block inverses in column major order (FORTRAN-like)
10678 
10679   Level: advanced
10680 
10681   Notes:
10682   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10683 
10684   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10685 
10686 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10687 @*/
10688 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10689 {
10690   PetscFunctionBegin;
10691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10692   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10693   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10694   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10695   PetscFunctionReturn(PETSC_SUCCESS);
10696 }
10697 
10698 /*@
10699   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10700 
10701   Collective
10702 
10703   Input Parameters:
10704 + A - the matrix
10705 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10706 
10707   Level: advanced
10708 
10709   Note:
10710   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10711 
10712 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10713 @*/
10714 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10715 {
10716   const PetscScalar *vals;
10717   PetscInt          *dnnz;
10718   PetscInt           m, rstart, rend, bs, i, j;
10719 
10720   PetscFunctionBegin;
10721   PetscCall(MatInvertBlockDiagonal(A, &vals));
10722   PetscCall(MatGetBlockSize(A, &bs));
10723   PetscCall(MatGetLocalSize(A, &m, NULL));
10724   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10725   PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs));
10726   PetscCall(PetscMalloc1(m / bs, &dnnz));
10727   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10728   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10729   PetscCall(PetscFree(dnnz));
10730   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10731   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10732   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10733   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10734   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10735   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10736   PetscFunctionReturn(PETSC_SUCCESS);
10737 }
10738 
10739 /*@
10740   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10741   via `MatTransposeColoringCreate()`.
10742 
10743   Collective
10744 
10745   Input Parameter:
10746 . c - coloring context
10747 
10748   Level: intermediate
10749 
10750 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10751 @*/
10752 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10753 {
10754   MatTransposeColoring matcolor = *c;
10755 
10756   PetscFunctionBegin;
10757   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10758   if (--((PetscObject)matcolor)->refct > 0) {
10759     matcolor = NULL;
10760     PetscFunctionReturn(PETSC_SUCCESS);
10761   }
10762 
10763   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10764   PetscCall(PetscFree(matcolor->rows));
10765   PetscCall(PetscFree(matcolor->den2sp));
10766   PetscCall(PetscFree(matcolor->colorforcol));
10767   PetscCall(PetscFree(matcolor->columns));
10768   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10769   PetscCall(PetscHeaderDestroy(c));
10770   PetscFunctionReturn(PETSC_SUCCESS);
10771 }
10772 
10773 /*@
10774   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10775   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10776   `MatTransposeColoring` to sparse `B`.
10777 
10778   Collective
10779 
10780   Input Parameters:
10781 + coloring - coloring context created with `MatTransposeColoringCreate()`
10782 - B        - sparse matrix
10783 
10784   Output Parameter:
10785 . Btdense - dense matrix $B^T$
10786 
10787   Level: developer
10788 
10789   Note:
10790   These are used internally for some implementations of `MatRARt()`
10791 
10792 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10793 @*/
10794 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10795 {
10796   PetscFunctionBegin;
10797   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10798   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10799   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10800 
10801   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10802   PetscFunctionReturn(PETSC_SUCCESS);
10803 }
10804 
10805 /*@
10806   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10807   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10808   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10809   $C_{sp}$ from $C_{den}$.
10810 
10811   Collective
10812 
10813   Input Parameters:
10814 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10815 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10816 
10817   Output Parameter:
10818 . Csp - sparse matrix
10819 
10820   Level: developer
10821 
10822   Note:
10823   These are used internally for some implementations of `MatRARt()`
10824 
10825 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10826 @*/
10827 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10828 {
10829   PetscFunctionBegin;
10830   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10831   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10832   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10833 
10834   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10835   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10836   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10837   PetscFunctionReturn(PETSC_SUCCESS);
10838 }
10839 
10840 /*@
10841   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10842 
10843   Collective
10844 
10845   Input Parameters:
10846 + mat        - the matrix product C
10847 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10848 
10849   Output Parameter:
10850 . color - the new coloring context
10851 
10852   Level: intermediate
10853 
10854 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10855           `MatTransColoringApplyDenToSp()`
10856 @*/
10857 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10858 {
10859   MatTransposeColoring c;
10860   MPI_Comm             comm;
10861 
10862   PetscFunctionBegin;
10863   PetscAssertPointer(color, 3);
10864 
10865   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10866   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10867   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10868   c->ctype = iscoloring->ctype;
10869   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10870   *color = c;
10871   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10872   PetscFunctionReturn(PETSC_SUCCESS);
10873 }
10874 
10875 /*@
10876   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10877   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
10878 
10879   Not Collective
10880 
10881   Input Parameter:
10882 . mat - the matrix
10883 
10884   Output Parameter:
10885 . state - the current state
10886 
10887   Level: intermediate
10888 
10889   Notes:
10890   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10891   different matrices
10892 
10893   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10894 
10895   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10896 
10897 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10898 @*/
10899 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10900 {
10901   PetscFunctionBegin;
10902   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10903   *state = mat->nonzerostate;
10904   PetscFunctionReturn(PETSC_SUCCESS);
10905 }
10906 
10907 /*@
10908   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10909   matrices from each processor
10910 
10911   Collective
10912 
10913   Input Parameters:
10914 + comm   - the communicators the parallel matrix will live on
10915 . seqmat - the input sequential matrices
10916 . n      - number of local columns (or `PETSC_DECIDE`)
10917 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10918 
10919   Output Parameter:
10920 . mpimat - the parallel matrix generated
10921 
10922   Level: developer
10923 
10924   Note:
10925   The number of columns of the matrix in EACH processor MUST be the same.
10926 
10927 .seealso: [](ch_matrices), `Mat`
10928 @*/
10929 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10930 {
10931   PetscMPIInt size;
10932 
10933   PetscFunctionBegin;
10934   PetscCallMPI(MPI_Comm_size(comm, &size));
10935   if (size == 1) {
10936     if (reuse == MAT_INITIAL_MATRIX) {
10937       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10938     } else {
10939       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10940     }
10941     PetscFunctionReturn(PETSC_SUCCESS);
10942   }
10943 
10944   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");
10945 
10946   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10947   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10948   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10949   PetscFunctionReturn(PETSC_SUCCESS);
10950 }
10951 
10952 /*@
10953   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10954 
10955   Collective
10956 
10957   Input Parameters:
10958 + A - the matrix to create subdomains from
10959 - N - requested number of subdomains
10960 
10961   Output Parameters:
10962 + n   - number of subdomains resulting on this MPI process
10963 - iss - `IS` list with indices of subdomains on this MPI process
10964 
10965   Level: advanced
10966 
10967   Note:
10968   The number of subdomains must be smaller than the communicator size
10969 
10970 .seealso: [](ch_matrices), `Mat`, `IS`
10971 @*/
10972 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10973 {
10974   MPI_Comm    comm, subcomm;
10975   PetscMPIInt size, rank, color;
10976   PetscInt    rstart, rend, k;
10977 
10978   PetscFunctionBegin;
10979   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10980   PetscCallMPI(MPI_Comm_size(comm, &size));
10981   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10982   PetscCheck(N >= 1 && N < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N);
10983   *n    = 1;
10984   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
10985   color = rank / k;
10986   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10987   PetscCall(PetscMalloc1(1, iss));
10988   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10989   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10990   PetscCallMPI(MPI_Comm_free(&subcomm));
10991   PetscFunctionReturn(PETSC_SUCCESS);
10992 }
10993 
10994 /*@
10995   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10996 
10997   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10998   If they are not the same, uses `MatMatMatMult()`.
10999 
11000   Once the coarse grid problem is constructed, correct for interpolation operators
11001   that are not of full rank, which can legitimately happen in the case of non-nested
11002   geometric multigrid.
11003 
11004   Input Parameters:
11005 + restrct     - restriction operator
11006 . dA          - fine grid matrix
11007 . interpolate - interpolation operator
11008 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11009 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11010 
11011   Output Parameter:
11012 . A - the Galerkin coarse matrix
11013 
11014   Options Database Key:
11015 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11016 
11017   Level: developer
11018 
11019   Note:
11020   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11021 
11022 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11023 @*/
11024 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11025 {
11026   IS  zerorows;
11027   Vec diag;
11028 
11029   PetscFunctionBegin;
11030   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11031   /* Construct the coarse grid matrix */
11032   if (interpolate == restrct) {
11033     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11034   } else {
11035     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11036   }
11037 
11038   /* If the interpolation matrix is not of full rank, A will have zero rows.
11039      This can legitimately happen in the case of non-nested geometric multigrid.
11040      In that event, we set the rows of the matrix to the rows of the identity,
11041      ignoring the equations (as the RHS will also be zero). */
11042 
11043   PetscCall(MatFindZeroRows(*A, &zerorows));
11044 
11045   if (zerorows != NULL) { /* if there are any zero rows */
11046     PetscCall(MatCreateVecs(*A, &diag, NULL));
11047     PetscCall(MatGetDiagonal(*A, diag));
11048     PetscCall(VecISSet(diag, zerorows, 1.0));
11049     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11050     PetscCall(VecDestroy(&diag));
11051     PetscCall(ISDestroy(&zerorows));
11052   }
11053   PetscFunctionReturn(PETSC_SUCCESS);
11054 }
11055 
11056 /*@C
11057   MatSetOperation - Allows user to set a matrix operation for any matrix type
11058 
11059   Logically Collective
11060 
11061   Input Parameters:
11062 + mat - the matrix
11063 . op  - the name of the operation
11064 - f   - the function that provides the operation
11065 
11066   Level: developer
11067 
11068   Example Usage:
11069 .vb
11070   extern PetscErrorCode usermult(Mat, Vec, Vec);
11071 
11072   PetscCall(MatCreateXXX(comm, ..., &A));
11073   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11074 .ve
11075 
11076   Notes:
11077   See the file `include/petscmat.h` for a complete list of matrix
11078   operations, which all have the form MATOP_<OPERATION>, where
11079   <OPERATION> is the name (in all capital letters) of the
11080   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11081 
11082   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11083   sequence as the usual matrix interface routines, since they
11084   are intended to be accessed via the usual matrix interface
11085   routines, e.g.,
11086 .vb
11087   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11088 .ve
11089 
11090   In particular each function MUST return `PETSC_SUCCESS` on success and
11091   nonzero on failure.
11092 
11093   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11094 
11095 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11096 @*/
11097 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11098 {
11099   PetscFunctionBegin;
11100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11101   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11102   (((void (**)(void))mat->ops)[op]) = f;
11103   PetscFunctionReturn(PETSC_SUCCESS);
11104 }
11105 
11106 /*@C
11107   MatGetOperation - Gets a matrix operation for any matrix type.
11108 
11109   Not Collective
11110 
11111   Input Parameters:
11112 + mat - the matrix
11113 - op  - the name of the operation
11114 
11115   Output Parameter:
11116 . f - the function that provides the operation
11117 
11118   Level: developer
11119 
11120   Example Usage:
11121 .vb
11122   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11123 
11124   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11125 .ve
11126 
11127   Notes:
11128   See the file include/petscmat.h for a complete list of matrix
11129   operations, which all have the form MATOP_<OPERATION>, where
11130   <OPERATION> is the name (in all capital letters) of the
11131   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11132 
11133   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11134 
11135 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11136 @*/
11137 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11138 {
11139   PetscFunctionBegin;
11140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11141   *f = (((void (**)(void))mat->ops)[op]);
11142   PetscFunctionReturn(PETSC_SUCCESS);
11143 }
11144 
11145 /*@
11146   MatHasOperation - Determines whether the given matrix supports the particular operation.
11147 
11148   Not Collective
11149 
11150   Input Parameters:
11151 + mat - the matrix
11152 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11153 
11154   Output Parameter:
11155 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11156 
11157   Level: advanced
11158 
11159   Note:
11160   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11161 
11162 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11163 @*/
11164 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11165 {
11166   PetscFunctionBegin;
11167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11168   PetscAssertPointer(has, 3);
11169   if (mat->ops->hasoperation) {
11170     PetscUseTypeMethod(mat, hasoperation, op, has);
11171   } else {
11172     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11173     else {
11174       *has = PETSC_FALSE;
11175       if (op == MATOP_CREATE_SUBMATRIX) {
11176         PetscMPIInt size;
11177 
11178         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11179         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11180       }
11181     }
11182   }
11183   PetscFunctionReturn(PETSC_SUCCESS);
11184 }
11185 
11186 /*@
11187   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11188 
11189   Collective
11190 
11191   Input Parameter:
11192 . mat - the matrix
11193 
11194   Output Parameter:
11195 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11196 
11197   Level: beginner
11198 
11199 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11200 @*/
11201 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11202 {
11203   PetscFunctionBegin;
11204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11205   PetscValidType(mat, 1);
11206   PetscAssertPointer(cong, 2);
11207   if (!mat->rmap || !mat->cmap) {
11208     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11209     PetscFunctionReturn(PETSC_SUCCESS);
11210   }
11211   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11212     PetscCall(PetscLayoutSetUp(mat->rmap));
11213     PetscCall(PetscLayoutSetUp(mat->cmap));
11214     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11215     if (*cong) mat->congruentlayouts = 1;
11216     else mat->congruentlayouts = 0;
11217   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11218   PetscFunctionReturn(PETSC_SUCCESS);
11219 }
11220 
11221 PetscErrorCode MatSetInf(Mat A)
11222 {
11223   PetscFunctionBegin;
11224   PetscUseTypeMethod(A, setinf);
11225   PetscFunctionReturn(PETSC_SUCCESS);
11226 }
11227 
11228 /*@
11229   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
11230   and possibly removes small values from the graph structure.
11231 
11232   Collective
11233 
11234   Input Parameters:
11235 + A       - the matrix
11236 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11237 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11238 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11239 . num_idx - size of 'index' array
11240 - index   - array of block indices to use for graph strength of connection weight
11241 
11242   Output Parameter:
11243 . graph - the resulting graph
11244 
11245   Level: advanced
11246 
11247 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11248 @*/
11249 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11250 {
11251   PetscFunctionBegin;
11252   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11253   PetscValidType(A, 1);
11254   PetscValidLogicalCollectiveBool(A, scale, 3);
11255   PetscAssertPointer(graph, 7);
11256   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11257   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11258   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11259   PetscFunctionReturn(PETSC_SUCCESS);
11260 }
11261 
11262 /*@
11263   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11264   meaning the same memory is used for the matrix, and no new memory is allocated.
11265 
11266   Collective
11267 
11268   Input Parameters:
11269 + A    - the matrix
11270 - 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
11271 
11272   Level: intermediate
11273 
11274   Developer Note:
11275   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11276   of the arrays in the data structure are unneeded.
11277 
11278 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11279 @*/
11280 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11281 {
11282   PetscFunctionBegin;
11283   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11284   PetscUseTypeMethod(A, eliminatezeros, keep);
11285   PetscFunctionReturn(PETSC_SUCCESS);
11286 }
11287