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